OLD | NEW |
1 /* ***** BEGIN LICENSE BLOCK ***** | 1 /* ***** BEGIN LICENSE BLOCK ***** |
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
3 * | 3 * |
4 * The contents of this file are subject to the Mozilla Public License Version | 4 * The contents of this file are subject to the Mozilla Public License Version |
5 * 1.1 (the "License"); you may not use this file except in compliance with | 5 * 1.1 (the "License"); you may not use this file except in compliance with |
6 * the License. You may obtain a copy of the License at | 6 * the License. You may obtain a copy of the License at |
7 * http://www.mozilla.org/MPL/ | 7 * http://www.mozilla.org/MPL/ |
8 * | 8 * |
9 * Software distributed under the License is distributed on an "AS IS" basis, | 9 * Software distributed under the License is distributed on an "AS IS" basis, |
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
(...skipping 17 matching lines...) Expand all Loading... |
28 * under the terms of either the GPL or the LGPL, and not to allow others to | 28 * under the terms of either the GPL or the LGPL, and not to allow others to |
29 * use your version of this file under the terms of the MPL, indicate your | 29 * use your version of this file under the terms of the MPL, indicate your |
30 * decision by deleting the provisions above and replace them with the notice | 30 * decision by deleting the provisions above and replace them with the notice |
31 * and other provisions required by the GPL or the LGPL. If you do not delete | 31 * and other provisions required by the GPL or the LGPL. If you do not delete |
32 * the provisions above, a recipient may use your version of this file under | 32 * the provisions above, a recipient may use your version of this file under |
33 * the terms of any one of the MPL, the GPL or the LGPL. | 33 * the terms of any one of the MPL, the GPL or the LGPL. |
34 * | 34 * |
35 * ***** END LICENSE BLOCK ***** */ | 35 * ***** END LICENSE BLOCK ***** */ |
36 | 36 |
37 #ifdef DEBUG | 37 #ifdef DEBUG |
38 static const char CVS_ID[] = "@(#) $RCSfile: arena.c,v $ $Revision: 1.12 $ $Date
: 2008/05/13 01:22:35 $"; | 38 static const char CVS_ID[] = "@(#) $RCSfile: arena.c,v $ $Revision: 1.13 $ $Date
: 2010/03/15 08:29:31 $"; |
39 #endif /* DEBUG */ | 39 #endif /* DEBUG */ |
40 | 40 |
41 /* | 41 /* |
42 * arena.c | 42 * arena.c |
43 * | 43 * |
44 * This contains the implementation of NSS's thread-safe arenas. | 44 * This contains the implementation of NSS's thread-safe arenas. |
45 */ | 45 */ |
46 | 46 |
47 #ifndef BASE_H | 47 #ifndef BASE_H |
48 #include "base.h" | 48 #include "base.h" |
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 * A pointer to the replacement segment of memory | 1019 * A pointer to the replacement segment of memory |
1020 */ | 1020 */ |
1021 | 1021 |
1022 NSS_EXTERN void * | 1022 NSS_EXTERN void * |
1023 nss_ZRealloc | 1023 nss_ZRealloc |
1024 ( | 1024 ( |
1025 void *pointer, | 1025 void *pointer, |
1026 PRUint32 newSize | 1026 PRUint32 newSize |
1027 ) | 1027 ) |
1028 { | 1028 { |
| 1029 NSSArena *arena; |
1029 struct pointer_header *h, *new_h; | 1030 struct pointer_header *h, *new_h; |
1030 PRUint32 my_newSize = newSize + sizeof(struct pointer_header); | 1031 PRUint32 my_newSize = newSize + sizeof(struct pointer_header); |
1031 void *rv; | 1032 void *rv; |
1032 | 1033 |
1033 if( my_newSize < sizeof(struct pointer_header) ) { | 1034 if( my_newSize < sizeof(struct pointer_header) ) { |
1034 /* Wrapped */ | 1035 /* Wrapped */ |
1035 nss_SetError(NSS_ERROR_NO_MEMORY); | 1036 nss_SetError(NSS_ERROR_NO_MEMORY); |
1036 return (void *)NULL; | 1037 return (void *)NULL; |
1037 } | 1038 } |
1038 | 1039 |
1039 if( (void *)NULL == pointer ) { | 1040 if( (void *)NULL == pointer ) { |
1040 nss_SetError(NSS_ERROR_INVALID_POINTER); | 1041 nss_SetError(NSS_ERROR_INVALID_POINTER); |
1041 return (void *)NULL; | 1042 return (void *)NULL; |
1042 } | 1043 } |
1043 | 1044 |
1044 h = (struct pointer_header *)((char *)pointer | 1045 h = (struct pointer_header *)((char *)pointer |
1045 - sizeof(struct pointer_header)); | 1046 - sizeof(struct pointer_header)); |
1046 | 1047 |
1047 /* Check any magic here */ | 1048 /* Check any magic here */ |
1048 | 1049 |
1049 if( newSize == h->size ) { | 1050 if( newSize == h->size ) { |
1050 /* saves thrashing */ | 1051 /* saves thrashing */ |
1051 return pointer; | 1052 return pointer; |
1052 } | 1053 } |
1053 | 1054 |
1054 if( (NSSArena *)NULL == h->arena ) { | 1055 arena = h->arena; |
| 1056 if (!arena) { |
1055 /* Heap */ | 1057 /* Heap */ |
1056 new_h = (struct pointer_header *)PR_Calloc(1, my_newSize); | 1058 new_h = (struct pointer_header *)PR_Calloc(1, my_newSize); |
1057 if( (struct pointer_header *)NULL == new_h ) { | 1059 if( (struct pointer_header *)NULL == new_h ) { |
1058 nss_SetError(NSS_ERROR_NO_MEMORY); | 1060 nss_SetError(NSS_ERROR_NO_MEMORY); |
1059 return (void *)NULL; | 1061 return (void *)NULL; |
1060 } | 1062 } |
1061 | 1063 |
1062 new_h->arena = (NSSArena *)NULL; | 1064 new_h->arena = (NSSArena *)NULL; |
1063 new_h->size = newSize; | 1065 new_h->size = newSize; |
1064 rv = (void *)((char *)new_h + sizeof(struct pointer_header)); | 1066 rv = (void *)((char *)new_h + sizeof(struct pointer_header)); |
1065 | 1067 |
1066 if( newSize > h->size ) { | 1068 if( newSize > h->size ) { |
1067 (void)nsslibc_memcpy(rv, pointer, h->size); | 1069 (void)nsslibc_memcpy(rv, pointer, h->size); |
1068 (void)nsslibc_memset(&((char *)rv)[ h->size ], | 1070 (void)nsslibc_memset(&((char *)rv)[ h->size ], |
1069 0, (newSize - h->size)); | 1071 0, (newSize - h->size)); |
1070 } else { | 1072 } else { |
1071 (void)nsslibc_memcpy(rv, pointer, newSize); | 1073 (void)nsslibc_memcpy(rv, pointer, newSize); |
1072 } | 1074 } |
1073 | 1075 |
1074 (void)nsslibc_memset(pointer, 0, h->size); | 1076 (void)nsslibc_memset(pointer, 0, h->size); |
1075 h->size = 0; | 1077 h->size = 0; |
1076 PR_Free(h); | 1078 PR_Free(h); |
1077 | 1079 |
1078 return rv; | 1080 return rv; |
1079 } else { | 1081 } else { |
1080 void *p; | 1082 void *p; |
1081 /* Arena */ | 1083 /* Arena */ |
1082 #ifdef NSSDEBUG | 1084 #ifdef NSSDEBUG |
1083 if( PR_SUCCESS != nssArena_verifyPointer(h->arena) ) { | 1085 if (PR_SUCCESS != nssArena_verifyPointer(arena)) { |
1084 return (void *)NULL; | 1086 return (void *)NULL; |
1085 } | 1087 } |
1086 #endif /* NSSDEBUG */ | 1088 #endif /* NSSDEBUG */ |
1087 | 1089 |
1088 if( (PRLock *)NULL == h->arena->lock ) { | 1090 if (!arena->lock) { |
1089 /* Just got destroyed.. so this pointer is invalid */ | 1091 /* Just got destroyed.. so this pointer is invalid */ |
1090 nss_SetError(NSS_ERROR_INVALID_POINTER); | 1092 nss_SetError(NSS_ERROR_INVALID_POINTER); |
1091 return (void *)NULL; | 1093 return (void *)NULL; |
1092 } | 1094 } |
1093 PR_Lock(h->arena->lock); | 1095 PR_Lock(arena->lock); |
1094 | 1096 |
1095 #ifdef ARENA_THREADMARK | 1097 #ifdef ARENA_THREADMARK |
1096 if( (PRThread *)NULL != h->arena->marking_thread ) { | 1098 if (arena->marking_thread) { |
1097 if( PR_GetCurrentThread() != h->arena->marking_thread ) { | 1099 if (PR_GetCurrentThread() != arena->marking_thread) { |
1098 PR_Unlock(h->arena->lock); | 1100 PR_Unlock(arena->lock); |
1099 nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD); | 1101 nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD); |
1100 return (void *)NULL; | 1102 return (void *)NULL; |
1101 } | 1103 } |
1102 } | 1104 } |
1103 #endif /* ARENA_THREADMARK */ | 1105 #endif /* ARENA_THREADMARK */ |
1104 | 1106 |
1105 if( newSize < h->size ) { | 1107 if( newSize < h->size ) { |
1106 /* | 1108 /* |
1107 * We have no general way of returning memory to the arena | 1109 * We have no general way of returning memory to the arena |
1108 * (mark/release doesn't work because things may have been | 1110 * (mark/release doesn't work because things may have been |
1109 * allocated after this object), so the memory is gone | 1111 * allocated after this object), so the memory is gone |
1110 * anyway. We might as well just return the same pointer to | 1112 * anyway. We might as well just return the same pointer to |
1111 * the user, saying "yeah, uh-hunh, you can only use less of | 1113 * the user, saying "yeah, uh-hunh, you can only use less of |
1112 * it now." We'll zero the leftover part, of course. And | 1114 * it now." We'll zero the leftover part, of course. And |
1113 * in fact we might as well *not* adjust h->size-- this way, | 1115 * in fact we might as well *not* adjust h->size-- this way, |
1114 * if the user reallocs back up to something not greater than | 1116 * if the user reallocs back up to something not greater than |
1115 * the original size, then voila, there's the memory! This | 1117 * the original size, then voila, there's the memory! This |
1116 * way a thrash big/small/big/small doesn't burn up the arena. | 1118 * way a thrash big/small/big/small doesn't burn up the arena. |
1117 */ | 1119 */ |
1118 char *extra = &((char *)pointer)[ newSize ]; | 1120 char *extra = &((char *)pointer)[ newSize ]; |
1119 (void)nsslibc_memset(extra, 0, (h->size - newSize)); | 1121 (void)nsslibc_memset(extra, 0, (h->size - newSize)); |
1120 PR_Unlock(h->arena->lock); | 1122 PR_Unlock(arena->lock); |
1121 return pointer; | 1123 return pointer; |
1122 } | 1124 } |
1123 | 1125 |
1124 PR_ARENA_ALLOCATE(p, &h->arena->pool, my_newSize); | 1126 PR_ARENA_ALLOCATE(p, &arena->pool, my_newSize); |
1125 if( (void *)NULL == p ) { | 1127 if( (void *)NULL == p ) { |
1126 PR_Unlock(h->arena->lock); | 1128 PR_Unlock(arena->lock); |
1127 nss_SetError(NSS_ERROR_NO_MEMORY); | 1129 nss_SetError(NSS_ERROR_NO_MEMORY); |
1128 return (void *)NULL; | 1130 return (void *)NULL; |
1129 } | 1131 } |
1130 | 1132 |
1131 new_h = (struct pointer_header *)p; | 1133 new_h = (struct pointer_header *)p; |
1132 new_h->arena = h->arena; | 1134 new_h->arena = arena; |
1133 new_h->size = newSize; | 1135 new_h->size = newSize; |
1134 rv = (void *)((char *)new_h + sizeof(struct pointer_header)); | 1136 rv = (void *)((char *)new_h + sizeof(struct pointer_header)); |
1135 if (rv != pointer) { | 1137 if (rv != pointer) { |
1136 (void)nsslibc_memcpy(rv, pointer, h->size); | 1138 (void)nsslibc_memcpy(rv, pointer, h->size); |
1137 (void)nsslibc_memset(pointer, 0, h->size); | 1139 (void)nsslibc_memset(pointer, 0, h->size); |
1138 } | 1140 } |
1139 (void)nsslibc_memset(&((char *)rv)[ h->size ], 0, (newSize - h->size)); | 1141 (void)nsslibc_memset(&((char *)rv)[ h->size ], 0, (newSize - h->size)); |
1140 h->arena = (NSSArena *)NULL; | 1142 h->arena = (NSSArena *)NULL; |
1141 h->size = 0; | 1143 h->size = 0; |
1142 PR_Unlock(new_h->arena->lock); | 1144 PR_Unlock(arena->lock); |
1143 return rv; | 1145 return rv; |
1144 } | 1146 } |
1145 /*NOTREACHED*/ | 1147 /*NOTREACHED*/ |
1146 } | 1148 } |
1147 | 1149 |
1148 PRStatus | 1150 PRStatus |
1149 nssArena_Shutdown(void) | 1151 nssArena_Shutdown(void) |
1150 { | 1152 { |
1151 PRStatus rv = PR_SUCCESS; | 1153 PRStatus rv = PR_SUCCESS; |
1152 #ifdef DEBUG | 1154 #ifdef DEBUG |
1153 rv = nssPointerTracker_finalize(&arena_pointer_tracker); | 1155 rv = nssPointerTracker_finalize(&arena_pointer_tracker); |
1154 #endif | 1156 #endif |
1155 return rv; | 1157 return rv; |
1156 } | 1158 } |
OLD | NEW |