]>
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
);
86 nsfreeall(POOL_SSTRING
);
89 static void salloc(void) {
90 ssmem
=(char *)nsmalloc(POOL_SSTRING
, SSTRING_ALLOC
);
91 ssmemfree
=SSTRING_ALLOC
;
93 #endif /* SSTRING_MMAP */
95 sstring
*findsstring(const char *str
) {
96 unsigned int hash
=crc32(str
)%SSTRING_HASHSIZE
;
99 for (ss
=sshash
[hash
];ss
;ss
=ss
->next
)
100 if (!strcmp(str
, sstring_content(ss
)))
106 void sstring_enhash(sstring
*ss
) {
107 unsigned int hash
=crc32(sstring_content(ss
))%SSTRING_HASHSIZE
;
109 ss
->next
=sshash
[hash
];
113 void sstring_dehash(sstring
*ss
) {
114 unsigned int hash
=crc32(sstring_content(ss
))%SSTRING_HASHSIZE
;
117 for (ssh
=sshash
[hash
],ssp
=NULL
; ssh
; ssp
=ssh
,ssh
=ssh
->next
) {
120 sshash
[hash
]=ss
->next
;
125 if (ssp
->block
!=ss
->block
) {
138 Error("sstring",ERR_WARNING
,"sstring_dehash(): Unable to find string (ref=%lu, length=%d) in hash: %s",ss
->refcount
,ss
->length
,sstring_content(ss
));
141 sstring
*getsstring(const char *inputstr
, int maxlen
) {
143 sstring
*retval
=NULL
;
144 int length
, foreignblock
;
145 char strbuf
[SSTRING_MAXLEN
];
147 /* getsstring() on a NULL pointer returns a NULL sstring.. */
148 if (inputstr
==NULL
) {
152 if (inputstr
[0]=='\0') {
156 if (maxlen
>SSTRING_MAX
) {
157 Error("sstring", ERR_ERROR
, "Attempt to allocate overlength string (maxlen=%d)",maxlen
);
161 /* Only count calls that actually did something */
164 /* Make a copy of the desired string to make things easier later */
165 for (length
=0;length
<maxlen
;length
++) {
166 strbuf
[length
]=inputstr
[length
];
174 /* If it's hashed this is easy */
175 if ((retval
=findsstring(strbuf
))) {
184 /* Check to see if an approximately correct
185 * sized string is available */
186 for(i
=0;i
<SSTRING_SLACK
;i
++) {
187 if (length
+i
>SSTRING_MAXLEN
)
190 if (freelist
[length
+i
]!=NULL
) {
191 retval
=freelist
[length
+i
];
192 freelist
[length
+i
]=retval
->next
;
196 retval
->alloc
=(length
+i
);
201 /* None found, allocate a new one */
203 /* Check for free memory */
204 if (ssmemfree
< (sizeof(sstring
)+length
)) {
205 /* Not enough for us - turn the remaining memory into a free string for later */
206 if (ssmemfree
>sizeof(sstring
)) {
207 retval
=(sstring
*)ssmem
;
210 retval
->block
=mblock
;
212 retval
->alloc
=(ssmemfree
-sizeof(sstring
));
223 retval
=(sstring
*)ssmem
;
224 ssmem
+=(sizeof(sstring
)+length
);
225 ssmemfree
-=(sizeof(sstring
)+length
);
227 retval
->alloc
=length
;
229 /* If there's a fragment left over, lump it into this allocation */
230 if (ssmemfree
< (sizeof(sstring
)+1)) {
231 retval
->alloc
+= ssmemfree
;
238 * At this point, retval points to a valid structure which is at
239 * least the right size and has the "alloc" value set correctly
242 retval
->length
=(length
-1);
243 strcpy(sstring_content(retval
),strbuf
);
248 retval
->block
= mblock
;
251 sstring_enhash(retval
);
253 #ifdef SSTRING_COMPAT
254 retval
->content
= retval
->__content
;
262 void freesstring(sstring
*inval
) {
265 /* Allow people to call this with a NULL value */
269 /* Only count calls that actually did something */
275 if (inval
->refcount
> 1) {
281 /* If refcount==0 it wasn't hashed, or protected */
283 sstring_dehash(inval
);
286 assert(alloc
<=SSTRING_MAXLEN
);
287 inval
->next
=freelist
[alloc
];
288 freelist
[alloc
]=inval
;
292 void sstringstats(int hooknum
, void *arg
) {
296 long statslev
=(long)arg
;
299 for(i
=0,j
=0;i
<=SSTRING_MAXLEN
;i
++) {
300 for(ssp
=freelist
[i
];ssp
;ssp
=ssp
->next
)
304 snprintf(buf
,512,"SString : %7d get calls, %7d free calls, %7d allocs, %7d strings free",getcalls
,freecalls
,allocs
,j
);
305 triggerhook(HOOK_CORE_STATSREPLY
,(void *)buf
);
311 struct mblock_list
*c
, *n
;
312 for (c
=mblock_head
;c
;c
=n
) {
314 munmap(c
->block
, SSTRING_ALLOC
);
318 static void salloc(void) {
319 struct mblock_list
*n
;
320 mblock
=mmap((void *)0, SSTRING_ALLOC
, PROT_WRITE
|PROT_READ
, MAP_PRIVATE
|MAP_ANON
, -1, 0);
322 n
=(struct mblock_list
*)mblock
;
324 n
->next
= mblock_head
;
327 ssmem
=(char *)mblock
+ sizeof(struct mblock_list
);
328 ssmemfree
=SSTRING_ALLOC
-sizeof(struct mblock_list
);
330 #endif /* SSTRING_MMAP */