From 6e520af3a16b771853b99c00e16e6c62411f420e Mon Sep 17 00:00:00 2001 From: Philippe Houdoin Date: Sat, 2 Aug 2003 00:35:03 +0000 Subject: [PATCH] Commit Be Inc. sample code string atomizer module, as we need it in userland (add-on) version too. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4190 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kits/net/new_stack/atomizer/atomizer.c | 445 ++++++++++++++++++ .../atomizer/atomizer_module_x86.proj | Bin 0 -> 11891 bytes 2 files changed, 445 insertions(+) create mode 100644 src/tests/kits/net/new_stack/atomizer/atomizer.c create mode 100644 src/tests/kits/net/new_stack/atomizer/atomizer_module_x86.proj diff --git a/src/tests/kits/net/new_stack/atomizer/atomizer.c b/src/tests/kits/net/new_stack/atomizer/atomizer.c new file mode 100644 index 0000000000..40cb3609b8 --- /dev/null +++ b/src/tests/kits/net/new_stack/atomizer/atomizer.c @@ -0,0 +1,445 @@ +/******************************************************************************* +/ +/ File: atomizer.c +/ +/ Description: Kernel module implementing kernel-space atomizer API +/ +/ Copyright 1999, Be Incorporated, All Rights Reserved. +/ This file may be used under the terms of the Be Sample Code License. +/ +*******************************************************************************/ + +#include +#include +#include +#include + +#include + + +#if DEBUG > 0 +#define ddprintf(x) dprintf x +#else +#define ddprintf(x) +#endif + +typedef struct { + sem_id sem; + int32 ben; +} benaphore; + +#define INIT_BEN(x) x.sem = create_sem(0, "an atomizer benaphore"); x.ben = 0; +#define ACQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem); +#define ACQUIRE_BEN_ON_ERROR(x, y) if((atomic_add(&(x.ben), 1)) >= 1) if (acquire_sem(x.sem) != B_OK) y; +#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem); +#define DELETE_BEN(x) delete_sem(x.sem); x.sem = -1; x.ben = 1; + +#define MIN_BLOCK_SIZE B_PAGE_SIZE + +typedef struct block_list block_list; + +struct block_list{ + block_list *next; + uint8 *free_space; + uint32 free_bytes; +}; + +typedef struct { + benaphore lock; /* serializes access to this atomizer */ + block_list *blocks; /* list of blocks holding atomized strings */ + uint32 count; /* number of atoms in this list */ + uint32 slots; /* total number of spaces in the allocated vector */ + uint8 **vector; /* sorted vector of pointers to atomized strings */ +} atomizer_data; + +typedef struct atomizer_data_list atomizer_data_list; + +struct atomizer_data_list { + char *name; /* the atomizer's name */ + atomizer_data *the_atomizer; /* the atomizer data */ + atomizer_data_list *next; /* the next atomizer in the list */ +}; + + +/* Module static data */ +const char atomizer_module_name[] = B_ATOMIZER_MODULE_NAME; +const char system_atomizer_name[] = B_SYSTEM_ATOMIZER_NAME; + +static benaphore module_lock; +static atomizer_data_list *atomizer_list; + +static atomizer_data * +make_atomizer(void) { + atomizer_data *ad; + + /* get space for atomizer data */ + ad = (atomizer_data *)malloc(sizeof(atomizer_data)); + if (ad) { + /* init locks */ + INIT_BEN(ad->lock); + if (ad->lock.sem >= 0) { + /* get first block for atomized strings */ + ad->blocks = (block_list *)malloc(MIN_BLOCK_SIZE); + if (ad->blocks) { + /* get vector for pointers to strings */ + ad->vector = (uint8 **)malloc(MIN_BLOCK_SIZE); + if (ad->vector) { + /* fill in the details */ + ad->blocks->next = 0; + ad->blocks->free_space = ((uint8 *)ad->blocks)+sizeof(block_list); + ad->blocks->free_bytes = MIN_BLOCK_SIZE - sizeof(block_list); + ad->count = 0; + ad->slots = MIN_BLOCK_SIZE / sizeof(uint8 *); + goto exit0; + } + /* oops, vector allocation failed */ + free(ad->blocks); + } + /* oops, block list allocation failed */ + DELETE_BEN(ad->lock); + } + /* oops, sem creation failed */ + free(ad); + ad = 0; + } +exit0: + ddprintf(("make_atomizer() returns %p\n", ad)); + return ad; +} + +static void +free_atomizer(atomizer_data *ad) { + block_list *bl, *blnext; + + /* Acquire the lock or fail trying. Better to not free + the data than corrupt the kernel heap */ + ACQUIRE_BEN_ON_ERROR(ad->lock, return); + /* walk the block_list, freeing them up */ + bl = ad->blocks; + while (bl) { + blnext = bl->next; + free(bl); + bl = blnext; + } + /* release vector of pointers to atomized strings */ + free(ad->vector); + /* delete the benaphore */ + DELETE_BEN(ad->lock); + /* finaly, release the atomizer data */ + free(ad); +} + +static const void * +find_or_make_atomizer(const char *string) { + atomizer_data_list *adl = atomizer_list; + atomizer_data_list *last = 0; + void * at = (void *)0; + + /* null or zero-length string means system atomizer */ + if (!string || (strlen(string) == 0)) string = system_atomizer_name; + + /* lock the atomizer list or fail returning a bogus atomizer */ + ACQUIRE_BEN_ON_ERROR(module_lock, return at); + ddprintf(("success locking module\n")); + while (adl && strcmp(adl->name, string)) { + last = adl; + adl = adl->next; + } + if (adl) { + at = (void *)adl->the_atomizer; + ddprintf(("asked for %s, returning %p\n", string, at)); + goto exit0; + } + ddprintf(("didn't find atomizer %s, making it\n", string)); + + adl = (atomizer_data_list *)malloc(sizeof(atomizer_data_list)); + if (adl) { + adl->the_atomizer = make_atomizer(); + if (adl->the_atomizer) { + adl->name = strdup(string); + if (adl->name) { + /* append to list */ + if (last) last->next = adl; + else atomizer_list = adl; + adl->next = 0; + at = (void *)adl->the_atomizer; + goto exit0; + } + free_atomizer(adl->the_atomizer); + } + free(adl); + } +exit0: + RELEASE_BEN(module_lock); + ddprintf(("find_or_make_atomizer() returning %p\n", at)); + return at; +} + +static status_t +init() +{ + ddprintf((T_ATOMIZER_MODULE_NAME": init()\n")); + /* init the module-wide benaphore */ + INIT_BEN(module_lock); + if (module_lock.sem >= 0) { + /* create list of atomizers */ + atomizer_list = 0; + if (find_or_make_atomizer(0)) + return B_OK; + /* oops, couldn't create system atomizer */ + DELETE_BEN(module_lock); + module_lock.sem = B_ERROR; + } + return module_lock.sem; +} + +static status_t +uninit() +{ + atomizer_data_list *adl; + /* aquire the module-wide lock. This is pure paranoia. + If it fails, all hell as broken loose, but we won't contribute + by corrupting the heap. */ + ddprintf((T_ATOMIZER_MODULE_NAME": uninit()\n")); + ACQUIRE_BEN_ON_ERROR(module_lock, return B_ERROR); + if (atomizer_list->next) { + ddprintf((T_ATOMIZER_MODULE_NAME": uninit called with non-system atomizers still active!\n")); + } + /* delete all of the atomizers. Ideally, there should only + be the system atomizer left */ + adl = atomizer_list; + while (adl) { + free_atomizer(adl->the_atomizer); + free(adl->name); + adl = adl->next; + } + /* free up the module-wide benaphore */ + DELETE_BEN(module_lock); + return B_OK; +} + +static status_t +std_ops(int32 op, ...) +{ + switch(op) { + case B_MODULE_INIT: + return init(); + case B_MODULE_UNINIT: + return uninit(); + default: + /* do nothing */ + ; + } + return -1; +} + +static status_t +delete_atomizer(const void * at) { + atomizer_data_list *adl; + atomizer_data_list *last = 0; + status_t result = B_ERROR; + + ACQUIRE_BEN_ON_ERROR(module_lock, return B_ERROR); + adl = atomizer_list; + while (adl && (adl->the_atomizer != (atomizer_data *)at)) { + last = adl; + adl = adl->next; + } + + if (adl) { + /* don't let clients delete the system atomizer */ + if (strcmp(adl->name, system_atomizer_name) != 0) { + free_atomizer(adl->the_atomizer); + free(adl->name); + /* the system atomizer is always first, so last will be non-zero */ + last->next = adl->next; + free(adl); + result = B_OK; + } + } + RELEASE_BEN(module_lock); + return result; +} + +static const void * +atomize(const void * at, const char *string, int create) { + atomizer_data_list *adl; + void *result = 0; + uint32 len; + + /* NULL and zero length strings aren't interned */ + if (!string || !(len = strlen(string))) return 0; + /* include the null terminator */ + len++; + /* own the list or fail trying */ + ACQUIRE_BEN_ON_ERROR(module_lock, return 0); + + /* use the system atomizer if none specified */ + if (at == ((void *)(-1))) at = atomizer_list->the_atomizer; + + /* walk the list of known atomizers, looking for a match */ + adl = atomizer_list; + while (adl && (adl->the_atomizer != (atomizer_data *)at)) { + adl = adl->next; + } + /* lock the atomizer *before* we give up control over the list */ + if (adl) ACQUIRE_BEN(adl->the_atomizer->lock); + /* allow list manipulations */ + RELEASE_BEN(module_lock); + /* did we find the one we wanted? */ + if (adl) { + atomizer_data *ad = adl->the_atomizer; + uint8 **vector = ad->vector; + uint32 count = ad->count; + uint32 low = 0; + uint32 high = count; + uint32 index = 0; + int test = -1; + /* do a binary search on the vector for a match */ + while (low < high) { + index = (low + high) / 2; + test = strcmp(string, (const char *)vector[index]); + if (test < 0) + high = index; + else if (test > 0) + low = index + 1; + else + break; + } + /* if match found, note result and return it */ + if (test == 0) { + result = vector[index]; + } else { + /* if we're not "just checking" */ + if (create) { + /* no match, so add to list */ + /* find first block with enough room */ + block_list *bl = ad->blocks; + while (bl->next) { + if (bl->free_bytes >= len) break; + bl = bl->next; + } + if (bl->free_bytes < len) { + /* allocate a block big enough to handle the string */ + size_t block_size = ((sizeof(block_list)+len+(MIN_BLOCK_SIZE-1)) & ~(MIN_BLOCK_SIZE-1)); + bl->next = (block_list *)malloc(block_size); + if (!bl->next) { + RELEASE_BEN(ad->lock); + return 0; + } + bl = bl->next; + bl->free_space = (uint8 *)(bl+1); + bl->free_bytes = block_size - sizeof(block_list); + } + /* actually intern an atom */ + result = bl->free_space; + memcpy(result, string, len); + bl->free_space += len; + bl->free_bytes -= len; + + /* insert the pointer in the vector */ + /* if the vector isn't big enough, realloc it */ + if (ad->count == ad->slots) { + size_t newslots = ad->slots + (MIN_BLOCK_SIZE / sizeof(uint8 *)); + uint8 **newvec = realloc(vector, newslots * sizeof(uint8 *)); + if (!newvec) { + /* bail, leaving the atom un-interned */ + RELEASE_BEN(ad->lock); + return 0; + } + ad->slots = newslots; + vector = ad->vector = newvec; + } + /* move all of the entries starting at index down one slot */ + memmove(vector + index + 1, vector + index, (count - index) * sizeof(uint8 *)); + /* insert the new pointer in the vector */ + vector[index] = result; + /* note new count */ + ad->count++; + } + } + RELEASE_BEN(ad->lock); + } + return result; +} + +const char * +string_for_token(const void *atomizer, const void *atom) { + /* someday, check for validity */ + return atom; +} + +status_t +get_next_atomizer_info(void **cookie, atomizer_info *info) { + atomizer_data_list *adl; + atomizer_data_list *atomizer = (atomizer_data_list *)*cookie; + status_t result = B_ERROR; + + ddprintf(("get_next_atomizer_info(cookie: %p, info: %p)\n", *cookie, info)); + /* a NULL info pointer? */ + if (!info) return result; + + ACQUIRE_BEN_ON_ERROR(module_lock, return result); + /* null? start over */ + if (!atomizer) atomizer = atomizer_list; + adl = atomizer_list; + while (adl && (adl != atomizer)) + adl = adl->next; + if (adl) { + *cookie = atomizer->next; + /* use a bogus cookie if no more left */ + if (!*cookie) *cookie = (void *)-1; + info->atomizer = atomizer->the_atomizer; + strncpy(info->name, adl->name, B_OS_NAME_LENGTH); + info->name[B_OS_NAME_LENGTH - 1] = '\0'; + info->atom_count = atomizer->the_atomizer->count; + result = B_OK; + } + RELEASE_BEN(module_lock); + return result; +} + +const void * +get_next_atom(const void *_atomizer, uint32 *cookie) { + atomizer_data_list *adl; + atomizer_data *atomizer = (atomizer_data *)_atomizer; + void *result = 0; + + /* validate the atomizer */ + ACQUIRE_BEN_ON_ERROR(module_lock, return 0); + adl = atomizer_list; + while (adl && (adl->the_atomizer != atomizer)) + adl = adl->next; + /* lock the atomizer *before* we give up control over the list */ + if (adl) ACQUIRE_BEN(atomizer->lock); + /* allow list manipulations */ + RELEASE_BEN(module_lock); + if (adl) { + if (*cookie < atomizer->count) { + result = atomizer->vector[*cookie]; + (*cookie)++; + } + RELEASE_BEN(atomizer->lock); + } + return result; +} + +static atomizer_module_info atomizer = { + { + atomizer_module_name, + 0, + std_ops + }, + find_or_make_atomizer, + delete_atomizer, + atomize, + string_for_token, + get_next_atomizer_info, + get_next_atom +}; + +_EXPORT atomizer_module_info *modules[] = { + &atomizer, + NULL +}; + diff --git a/src/tests/kits/net/new_stack/atomizer/atomizer_module_x86.proj b/src/tests/kits/net/new_stack/atomizer/atomizer_module_x86.proj new file mode 100644 index 0000000000000000000000000000000000000000..db0f56a89722583fbef9985270343b0e013a8912 GIT binary patch literal 11891 zcmeHNZ)hAv6rb&_?Imr@)g~rQ)m|;O+V*maSk#KmrI*HPlP*cDTC~^A-XvMGw|nkx zn$#jJC?cXCgrfC}2>QW~`biOyekj!sr3ikhDB_3Whq8)@pvaZ_d$Y62r49X)i&(rH zZg%IrdGF18Z)a!Uy_tbM`98+FC-a&+#@MzmHMh@ZjHwquqOMSI z$>$6Mw-oAfR4O;2E*sYT3C0wnV@h_^ar|tNALf=*&Q5T>$Xzcx%BizXO0_@O!u~MI z}zdPh8;m$G%|6K!riO(;jpuJb%M z{FmnZRd1~-e<(_Kcb4qWjpXtP`e3yVjSOmPv*#LxY11w`)1UpU1g*gJCXx z&)7FP#(wN=?H?Q-=uC~cx-rS!{U)CtaVEL_D?V;7vnIA)I`(F9SJ=wkeM3W?s>{c` zTYy@DdT4b-Q^;vrf%yy)_w7|zj86H!V|(*p5oL5qEr?v8GjMl1{0QPHhOr z4WnS0_9WoN71Di)ie4_m@w#t1c6KIHn$E~6e9ht$bCk8(HD8y*cCovcXSg-SXSgxt z>!a4y0+WAPmu}t7=&mtg9=@6)@X0d9C;+1ZzeJ5iUVT2}XSXbpnb=5|ty_hF8$uW9 zjvGQ38Qa|$x8Y0KOEu;Lp>NlqJ!{FIh{WOwGC^ z7}KR9n7g%o+iEokx;QtAE-F)81Ut2wv?ToSizglPUq7RMk;_>3dq1~(VOw_KDUI?N zow;(kuW0&?t5Fyy;w6e2&z?Pdu^Ih}f*&pso4VdG41`vy3UhWjrLt*pcVC$T8IMtb zlo>0VMmn?aezY5<;emz+>dOOinYg`Z%`Ovr@uzG4B2iy1X;|CvK*Iyo9*`kO2c?F9 zSD!2wb)RcUs}L6L)$Q>qeVoU73el1-Bk9_r@Tuh3PwB30+T()w(hQSi+FZp{O+Ke{#3;$P zNb-~zqsW2guE;gb8-#cw4)vahLsfG{M1qLrbgO^Yu7$$8xgi^^h6frRs5cMDC8jG1 z?^u$SI}zT^E_QNB*&GLe^OlrGC|GY3reSZx16T5ZTu|DEygW7`nL5P1yzcA7qR77c z5eHH>?>5AN26hYMOchY#KnM@`9K&0Ba>XDSYko=CB9t+rHZr{_;mUOrP5n(u5$G9qS0FdVP$YZb?^S z`Zef(|EuQkQkp}P5$;{cA-T(5PlkEmNGCDQz}g^vbGq{9&Ze*jc#=bRl0|o-IeAOE zBJiMl>*HjkAKE{>nw;%B`{wen2eM*X(u3L%$4;(ES31n~0w#R2Jzb&wcG8JxNEe~^ zBWr_J;E%3r7d8tV2>_n4bcOstpaS?L#xMQd7E&M4g@D(gFNC}&9%>hOq7}TvFX`xh zZg6cdJfXXqz!uI$;- z9^Nb4Doi4u+zyyz5Fhmsz74b=4z`EKvBag&CSJmSy(e-0uZ@ZGBf#fV>82C31cHa) zhdUGJiJtmt6^MBhmN*aA%k8YjVNoU9N z?u*_RqNjfP$1iLL%zkSRUcsKpBWNcv;Zm?6wtW@aJ+Hwhz`qTi$5H95$78_b#-NJ= z{gh_`|N2}@5Lj!2k!J>T^d1n+UQ`YB-cQ>D@$Mh&2nZ%T@kgs=yn3>qO4C*m=+jZm zTD64JYOE9rp0B&~$y!_~_}ncOTxZHRZC<#383ofe{TldVJC%DPJC#nYZ+DfE*RRq4 zoLsMEXzL6miQTmLWY3};vJ-{gP)*DA#scQ2xkhn1=UR{EL=uLP zJR^~)c(_z|}RA%gz?>mCi>+ZZjr=8Dii~5UQcV76m)Do0|FTS%OAR1~@?;q&f zf&3dp+z0R=V=c5(_#pLB2~c-#ZOsjsC5kaRP}hjv?wO3|Ot}Wn7*3J1f#Ka2y5cis zj2sD=z9%c=%v`s@==}rAM4eXx3CU451Kc>@QwyGDlB0ITvgD{_!1CzKnjDZ0e9tR^ YgcdiTFq58awV61$>EbYWH};7C0kV3osQ>@~ literal 0 HcmV?d00001