diff options
Diffstat (limited to 'src/lib/libc/stdlib/atexit.c')
| -rw-r--r-- | src/lib/libc/stdlib/atexit.c | 29 | 
1 files changed, 20 insertions, 9 deletions
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c index cb96bf0aa9..50f8ec9372 100644 --- a/src/lib/libc/stdlib/atexit.c +++ b/src/lib/libc/stdlib/atexit.c  | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: atexit.c,v 1.11 2005/10/26 18:55:26 otto Exp $ */ | 1 | /* $OpenBSD: atexit.c,v 1.12 2006/02/22 07:16:32 otto Exp $ */ | 
| 2 | /* | 2 | /* | 
| 3 | * Copyright (c) 2002 Daniel Hartmeier | 3 | * Copyright (c) 2002 Daniel Hartmeier | 
| 4 | * All rights reserved. | 4 | * All rights reserved. | 
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <stdlib.h> | 34 | #include <stdlib.h> | 
| 35 | #include <unistd.h> | 35 | #include <unistd.h> | 
| 36 | #include "atexit.h" | 36 | #include "atexit.h" | 
| 37 | #include "thread_private.h" | ||
| 37 | 38 | ||
| 38 | int __atexit_invalid = 1; | 39 | int __atexit_invalid = 1; | 
| 39 | struct atexit *__atexit; | 40 | struct atexit *__atexit; | 
| @@ -54,22 +55,25 @@ struct atexit *__atexit; | |||
| 54 | int | 55 | int | 
| 55 | atexit(void (*fn)(void)) | 56 | atexit(void (*fn)(void)) | 
| 56 | { | 57 | { | 
| 57 | struct atexit *p = __atexit; | 58 | struct atexit *p; | 
| 58 | int pgsize = getpagesize(); | 59 | int pgsize = getpagesize(); | 
| 60 | int ret = -1; | ||
| 59 | 61 | ||
| 60 | if (pgsize < sizeof(*p)) | 62 | if (pgsize < sizeof(*p)) | 
| 61 | return (-1); | 63 | return (-1); | 
| 64 | _ATEXIT_LOCK(); | ||
| 65 | p = __atexit; | ||
| 62 | if (p != NULL) { | 66 | if (p != NULL) { | 
| 63 | if (p->ind + 1 >= p->max) | 67 | if (p->ind + 1 >= p->max) | 
| 64 | p = NULL; | 68 | p = NULL; | 
| 65 | else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) | 69 | else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) | 
| 66 | return (-1); | 70 | goto unlock; | 
| 67 | } | 71 | } | 
| 68 | if (p == NULL) { | 72 | if (p == NULL) { | 
| 69 | p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, | 73 | p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, | 
| 70 | MAP_ANON | MAP_PRIVATE, -1, 0); | 74 | MAP_ANON | MAP_PRIVATE, -1, 0); | 
| 71 | if (p == MAP_FAILED) | 75 | if (p == MAP_FAILED) | 
| 72 | return (-1); | 76 | goto unlock; | 
| 73 | if (__atexit == NULL) { | 77 | if (__atexit == NULL) { | 
| 74 | p->fns[0] = NULL; | 78 | p->fns[0] = NULL; | 
| 75 | p->ind = 1; | 79 | p->ind = 1; | 
| @@ -84,8 +88,11 @@ atexit(void (*fn)(void)) | |||
| 84 | } | 88 | } | 
| 85 | p->fns[p->ind++] = fn; | 89 | p->fns[p->ind++] = fn; | 
| 86 | if (mprotect(p, pgsize, PROT_READ)) | 90 | if (mprotect(p, pgsize, PROT_READ)) | 
| 87 | return (-1); | 91 | goto unlock; | 
| 88 | return (0); | 92 | ret = 0; | 
| 93 | unlock: | ||
| 94 | _ATEXIT_UNLOCK(); | ||
| 95 | return (ret); | ||
| 89 | } | 96 | } | 
| 90 | 97 | ||
| 91 | /* | 98 | /* | 
| @@ -94,18 +101,20 @@ atexit(void (*fn)(void)) | |||
| 94 | void | 101 | void | 
| 95 | __atexit_register_cleanup(void (*fn)(void)) | 102 | __atexit_register_cleanup(void (*fn)(void)) | 
| 96 | { | 103 | { | 
| 97 | struct atexit *p = __atexit; | 104 | struct atexit *p; | 
| 98 | int pgsize = getpagesize(); | 105 | int pgsize = getpagesize(); | 
| 99 | 106 | ||
| 100 | if (pgsize < sizeof(*p)) | 107 | if (pgsize < sizeof(*p)) | 
| 101 | return; | 108 | return; | 
| 109 | _ATEXIT_LOCK(); | ||
| 110 | p = __atexit; | ||
| 102 | while (p != NULL && p->next != NULL) | 111 | while (p != NULL && p->next != NULL) | 
| 103 | p = p->next; | 112 | p = p->next; | 
| 104 | if (p == NULL) { | 113 | if (p == NULL) { | 
| 105 | p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, | 114 | p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, | 
| 106 | MAP_ANON | MAP_PRIVATE, -1, 0); | 115 | MAP_ANON | MAP_PRIVATE, -1, 0); | 
| 107 | if (p == MAP_FAILED) | 116 | if (p == MAP_FAILED) | 
| 108 | return; | 117 | goto unlock; | 
| 109 | p->ind = 1; | 118 | p->ind = 1; | 
| 110 | p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) / | 119 | p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) / | 
| 111 | sizeof(p->fns[0]); | 120 | sizeof(p->fns[0]); | 
| @@ -115,8 +124,10 @@ __atexit_register_cleanup(void (*fn)(void)) | |||
| 115 | __atexit_invalid = 0; | 124 | __atexit_invalid = 0; | 
| 116 | } else { | 125 | } else { | 
| 117 | if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) | 126 | if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) | 
| 118 | return; | 127 | goto unlock; | 
| 119 | } | 128 | } | 
| 120 | p->fns[0] = fn; | 129 | p->fns[0] = fn; | 
| 121 | mprotect(p, pgsize, PROT_READ); | 130 | mprotect(p, pgsize, PROT_READ); | 
| 131 | unlock: | ||
| 132 | _ATEXIT_UNLOCK(); | ||
| 122 | } | 133 | } | 
