]>
jfr.im git - irc/quakenet/newserv.git/blob - lib/sstring-new.c
1 /* sstring.h - Declaration of "static strings" functions */
3 #define COMPILING_SSTRING
7 #include "../core/hooks.h"
8 #include "../core/nsmalloc.h"
9 #include "../core/error.h"
10 #include "../lib/irc_string.h"
19 /* List of free stuff */
20 static sstring
*freelist
[SSTRING_MAXLEN
+1];
21 static sstring
*sshash
[SSTRING_HASHSIZE
];
23 /* Global variables to track allocated memory */
27 /* Statistics counters */
32 /* Internal functions */
33 static void sstringstats(int hooknum
, void *arg
);
34 static void salloc(void);
39 #define sunprotectb(x)
50 struct mblock_list
*next
;
53 static void *mblock_head
;
55 #define sunprotectb(x) mprotect(x, SSTRING_ALLOC, PROT_READ|PROT_WRITE);
56 #define sunprotect(x) sunprotectb((x)->block);
57 #define sprotect(x) mprotect((x)->block, SSTRING_ALLOC, PROT_READ);
60 #define MAP_ANON MAP_ANONYMOUS
63 #endif /* SSTRING_MMAP */
67 for(i
=0;i
<=SSTRING_MAXLEN
;i
++)
70 for(i
=0;i
<SSTRING_HASHSIZE
;i
++)
76 /* Initialise statistics counters */
81 registerhook(HOOK_CORE_STATSREQUEST
,&sstringstats
);
85 deregisterhook(HOOK_CORE_STATSREQUEST
,&sstringstats
);
88 nsfreeall(POOL_SSTRING
);
89 #endif /* SSTRING_MMAP */
93 static void salloc(void) {
94 ssmem
=(char *)nsmalloc(POOL_SSTRING
, SSTRING_ALLOC
);
95 ssmemfree
=SSTRING_ALLOC
;
97 #endif /* SSTRING_MMAP */
99 sstring
*findsstring(const char *str
) {
100 unsigned int hash
=crc32(str
)%SSTRING_HASHSIZE
;
103 for (ss
=sshash
[hash
];ss
;ss
=ss
->next
)
104 if (!strcmp(str
, sstring_content(ss
)))
110 void sstring_enhash(sstring
*ss
) {
111 unsigned int hash
=crc32(sstring_content(ss
))%SSTRING_HASHSIZE
;
113 ss
->next
=sshash
[hash
];
117 void sstring_dehash(sstring
*ss
) {
118 unsigned int hash
=crc32(sstring_content(ss
))%SSTRING_HASHSIZE
;
121 for (ssh
=sshash
[hash
],ssp
=NULL
; ssh
; ssp
=ssh
,ssh
=ssh
->next
) {
124 sshash
[hash
]=ss
->next
;
129 if (ssp
->block
!=ss
->block
) {
142 Error("sstring",ERR_WARNING
,"sstring_dehash(): Unable to find string (ref=%lu, length=%d) in hash: %s",ss
->refcount
,ss
->length
,sstring_content(ss
));
145 sstring
*getsstring(const char *inputstr
, int maxlen
) {
147 sstring
*retval
=NULL
;
148 int length
, foreignblock
;
149 char strbuf
[SSTRING_MAXLEN
];
151 /* getsstring() on a NULL pointer returns a NULL sstring.. */
152 if (inputstr
==NULL
) {
156 if (inputstr
[0]=='\0') {
160 if (maxlen
>SSTRING_MAX
) {
161 Error("sstring", ERR_ERROR
, "Attempt to allocate overlength string (maxlen=%d)",maxlen
);
165 /* Only count calls that actually did something */
168 /* Make a copy of the desired string to make things easier later */
169 for (length
=0;length
<maxlen
;length
++) {
170 strbuf
[length
]=inputstr
[length
];
178 /* If it's hashed this is easy */
179 if ((retval
=findsstring(strbuf
))) {
188 /* Check to see if an approximately correct
189 * sized string is available */
190 for(i
=0;i
<SSTRING_SLACK
;i
++) {
191 if (length
+i
>SSTRING_MAXLEN
)
194 if (freelist
[length
+i
]!=NULL
) {
195 retval
=freelist
[length
+i
];
196 freelist
[length
+i
]=retval
->next
;
200 retval
->alloc
=(length
+i
);
205 /* None found, allocate a new one */
207 /* Check for free memory */
208 if (ssmemfree
< (sizeof(sstring
)+length
)) {
209 /* Not enough for us - turn the remaining memory into a free string for later */
210 if (ssmemfree
>sizeof(sstring
)) {
211 retval
=(sstring
*)ssmem
;
214 retval
->block
=mblock
;
216 retval
->alloc
=(ssmemfree
-sizeof(sstring
));
227 retval
=(sstring
*)ssmem
;
228 ssmem
+=(sizeof(sstring
)+length
);
229 ssmemfree
-=(sizeof(sstring
)+length
);
231 retval
->alloc
=length
;
233 /* If there's a fragment left over, lump it into this allocation */
234 if (ssmemfree
< (sizeof(sstring
)+1)) {
235 retval
->alloc
+= ssmemfree
;
242 * At this point, retval points to a valid structure which is at
243 * least the right size and has the "alloc" value set correctly
246 retval
->length
=(length
-1);
247 strcpy(sstring_content(retval
),strbuf
);
252 retval
->block
= mblock
;
255 sstring_enhash(retval
);
257 #ifdef SSTRING_COMPAT
258 retval
->content
= retval
->__content
;
266 void freesstring(sstring
*inval
) {
269 /* Allow people to call this with a NULL value */
273 /* Only count calls that actually did something */
279 if (inval
->refcount
> 1) {
285 /* If refcount==0 it wasn't hashed, or protected */
287 sstring_dehash(inval
);
290 assert(alloc
<=SSTRING_MAXLEN
);
291 inval
->next
=freelist
[alloc
];
292 freelist
[alloc
]=inval
;
296 void sstringstats(int hooknum
, void *arg
) {
300 long statslev
=(long)arg
;
303 for(i
=0,j
=0;i
<=SSTRING_MAXLEN
;i
++) {
304 for(ssp
=freelist
[i
];ssp
;ssp
=ssp
->next
)
308 snprintf(buf
,512,"SString : %7d get calls, %7d free calls, %7d allocs, %7d strings free",getcalls
,freecalls
,allocs
,j
);
309 triggerhook(HOOK_CORE_STATSREPLY
,(void *)buf
);
315 struct mblock_list
*c
, *n
;
316 for (c
=mblock_head
;c
;c
=n
) {
318 munmap(c
->block
, SSTRING_ALLOC
);
322 static void salloc(void) {
323 struct mblock_list
*n
;
324 mblock
=mmap((void *)0, SSTRING_ALLOC
, PROT_WRITE
|PROT_READ
, MAP_PRIVATE
|MAP_ANON
, -1, 0);
326 n
=(struct mblock_list
*)mblock
;
328 n
->next
= mblock_head
;
331 ssmem
=(char *)mblock
+ sizeof(struct mblock_list
);
332 ssmemfree
=SSTRING_ALLOC
-sizeof(struct mblock_list
);
334 #endif /* SSTRING_MMAP */