void* kmalloc(int size) { int i = 0; int bkt_size = 0; bucket_desc_t* bkt = NULL; for (i=0; i<DESC_DIR_SIZE; i++) { bkt = bucket_dir[i]; bkt_size = 16*(1<<i); if (size < bkt_size) { break; } } // 没有合适的大小来分配size if (bkt == NULL) { return NULL; } // 寻找还可以分配的page while (bkt != NULL && bkt->free == NULL) { bkt = bkt->next; } // 如果所有的bucket都已经分配,new一块新的bucket if (bkt == NULL) { bkt = new_bucket(bkt_size); bkt->next = bucket_dir[i]; bucket_dir[i] = bkt; } bucket_block_t* p = bkt->free; bkt->free = p->next; return (void*)(p->addr); }
int main(int argc, char** argv) { bucketmap* bucket = new_bucket(10, dumb, NULL); char* line = read(); bucket = bucketify_file(argv[1], bucket, ':'); for ( ; ; ) { if (compare(line, GET_OPTION) == EQUAL) line = get_option(bucket); else if (compare(line, ADD_OPTION) == EQUAL) line = add_option(bucket); else if (compare(line, DEL_OPTION) == EQUAL) line = del_option(bucket); else if (compare(line, QUIT_OPTION) == EQUAL) break; else line = NULL; if (line) printf("%s\n", line); else printf("...\n"); line = read(); } save_bucket(bucket, "new_index.txt"); return 0; }
void kmalloc_init() { int i = 0; for (i=0; i<DESC_DIR_SIZE; i++) { bucket_dir[i] = new_bucket(16*(1<<i)); } }
void set_hashmap(HashMap* hm, V key, V value) { if (hm->map == NULL) { Bucket **bl = calloc(hm->size, sizeof(Bucket*)); hm->map = bl; } uint32_t hash = get_hash(key) % hm->size; Bucket* b = hm->map[hash]; if (b == NULL) { hm->map[hash] = new_bucket(key, value); hm->used++; } else { if (set_to_bucket(b, key, value)) { hm->used++; } } if (hm->used > hm->size) { resize_hashmap(hm, hm->size * 2); } }
// Helper function to split the bucket in 'table' at address 'address', // growing table if necessary static void split_bucket(InnerTable *innertable, int address, int table_no) { // FIRST, // do we need to grow the table? if (innertable->buckets[address]->depth == innertable->depth) { // yep, this bucket is down to its last pointer double_table(innertable); } // either way, now it's time to split this bucket // SECOND, // create a new bucket and update both buckets' depth Bucket *bucket = innertable->buckets[address]; int depth = bucket->depth; int first_address = bucket->id; int new_depth = depth + 1; bucket->depth = new_depth; // new bucket's first address will be a 1 bit plus the old first address int new_first_address = 1 << depth | first_address; Bucket *newbucket = new_bucket(new_first_address, new_depth); // THIRD, // redirect every second address pointing to this bucket to the new bucket // construct addresses by joining a bit 'prefix' and a bit 'suffix' // (defined below) // suffix: a 1 bit followed by the previous bucket bit address int bit_address = rightmostnbits(depth, first_address); int suffix = (1 << depth) | bit_address; // prefix: all bitstrings of length equal to the difference between the new // bucket depth and the table depth // use a for loop to enumerate all possible prefixes less than maxprefix: int maxprefix = 1 << (innertable->depth - new_depth); int prefix; for (prefix = 0; prefix < maxprefix; prefix++) { // construct address by joining this prefix and the suffix int a = (prefix << new_depth) | suffix; // redirect this table entry to point at the new bucket innertable->buckets[a] = newbucket; } // FINALLY, // filter the key from the old bucket into its rightful place in the new // table (which may be the old bucket, or may be the new bucket) // remove and reinsert the key int64 key = bucket->key; bucket->full = false; reinsert_key(innertable, key, table_no); }
// Helper function to initialise the InnerTable static InnerTable *initialise_inner_table(InnerTable *innertable) { innertable = malloc(sizeof (InnerTable)); assert(innertable); innertable->size = 1; innertable->buckets = malloc(sizeof *innertable->buckets); assert(innertable->buckets); innertable->buckets[0] = new_bucket(0, 0); innertable->depth = 0; innertable->nkeys = 0; return innertable; }
// initialise an extendible hash table with 'bucketsize' keys per bucket XtndblNHashTable *new_xtndbln_hash_table(int bucketsize) { XtndblNHashTable *table = malloc(sizeof *table); assert(table); table->size = 1; table->buckets = malloc(sizeof *table->buckets); assert(table->buckets); table->buckets[0] = new_bucket(0, 0, bucketsize); // Initialise the initial value table->depth = 0; table->bucketsize = bucketsize; table->stats.nbuckets = 1; table->stats.nkeys = 0; return table; }
bool set_to_bucket(Bucket* b, V key, V value) { if (equal(b->key, key)) { V tmp = b->value; b->value = add_ref(value); clear_ref(tmp); return false; } if (b->next == NULL) { b->next = new_bucket(key, value); return true; } else { return set_to_bucket(b->next, key, value); } }
void * malloc(size_t size) { pthread_mutex_lock(&thread_list_mutex); localthread* lt = get_localthread(pthread_self()); pthread_mutex_unlock(&thread_list_mutex); if (lt == NULL) { return NULL; } //let's save size regardless of allocation size //allocated memory will always be |size|memory........| size_t realsize = size + sizeof(size_t); void * ptr; //we allocate that memory if (realsize < MIN_SIZE) { //linear allocation with buckets bucket* res; pthread_mutex_lock(&(lt->small_bucket_mutex)); if (lt->small_list) { res = lt->small_list; lt->small_list = res->next; res->next = NULL; } pthread_mutex_unlock(&(lt->small_bucket_mutex)); if (res) { return res->mem; } res = new_bucket(MIN_SIZE); return res->mem; } else if (realsize < MAX_SIZE) { //clever allocation with heap } else { //dumb allocation with malloc_dumb ptr = mmap(NULL, realsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED) { return NULL; } } //in the end we record size and return ptr size_t * size_ptr = (size_t *) ptr; *(size_ptr) = realsize; return (void *) size_ptr + sizeof(size_t); }
void init_levels (void) { level_bucket = new_bucket(); LEVEL_NONE = 0; LEVEL_OTHER = add_new_level("OTHER"); add_new_level_alias(LEVEL_OTHER, "CRAP"); LEVEL_PUBLIC = add_new_level("PUBLICS"); LEVEL_MSG = add_new_level("MSGS"); LEVEL_NOTICE = add_new_level("NOTICES"); LEVEL_WALL = add_new_level("WALLS"); LEVEL_WALLOP = add_new_level("WALLOPS"); LEVEL_OPNOTE = add_new_level("OPNOTES"); LEVEL_SNOTE = add_new_level("SNOTES"); LEVEL_ACTION = add_new_level("ACTIONS"); LEVEL_DCC = add_new_level("DCCS"); LEVEL_CTCP = add_new_level("CTCPS"); LEVEL_INVITE = add_new_level("INVITES"); LEVEL_JOIN = add_new_level("JOINS"); LEVEL_NICK = add_new_level("NICKS"); LEVEL_TOPIC = add_new_level("TOPICS"); LEVEL_PART = add_new_level("PARTS"); LEVEL_QUIT = add_new_level("QUITS"); LEVEL_KICK = add_new_level("KICKS"); LEVEL_MODE = add_new_level("MODES"); LEVEL_OPERWALL = add_new_level("OPERWALL"); LEVEL_SYSERR = add_new_level("SYSERR"); LEVEL_USER1 = add_new_level("USER1"); LEVEL_USER2 = add_new_level("USER2"); LEVEL_USER3 = add_new_level("USER3"); LEVEL_USER4 = add_new_level("USER4"); LEVEL_USER5 = add_new_level("USER5"); LEVEL_USER6 = add_new_level("USER6"); LEVEL_USER7 = add_new_level("USER7"); LEVEL_USER8 = add_new_level("USER8"); LEVEL_USER9 = add_new_level("USER9"); LEVEL_USER10 = add_new_level("USER10"); LEVEL_ALL = 0x7FFFFFFF; }
/* * init_variables: initializes the string variables that can't really be * initialized properly above */ void init_variables_stage1 (void) { var_bucket = new_bucket(); VAR(ALLOW_C1_CHARS, BOOL, NULL) VAR(ALWAYS_SPLIT_BIGGEST, BOOL, NULL) VAR(BANNER, STR, NULL) VAR(BANNER_EXPAND, BOOL, NULL) VAR(BEEP, BOOL, NULL) VAR(CHANNEL_NAME_WIDTH, INT, update_all_status_wrapper) #define DEFAULT_CLIENT_INFORMATION IRCII_COMMENT VAR(CLIENT_INFORMATION, STR, NULL) VAR(CLOCK, BOOL, my_set_clock); VAR(CLOCK_24HOUR, BOOL, reset_clock); VAR(CLOCK_FORMAT, STR, set_clock_format); VAR(CLOCK_INTERVAL, INT, set_clock_interval); VAR(CMDCHARS, STR, NULL); VAR(COMMENT_HACK, BOOL, NULL); VAR(CONTINUED_LINE, STR, NULL); VAR(CPU_SAVER_AFTER, INT, set_cpu_saver_after); VAR(CPU_SAVER_EVERY, INT, set_cpu_saver_every); VAR(CURRENT_WINDOW_LEVEL, STR, set_current_window_mask); VAR(DCC_AUTO_SEND_REJECTS, BOOL, NULL); VAR(DCC_CONNECT_TIMEOUT, INT, NULL); VAR(DCC_DEQUOTE_FILENAMES, BOOL, NULL); VAR(DCC_LONG_PATHNAMES, BOOL, NULL); VAR(DCC_SLIDING_WINDOW, INT, NULL); VAR(DCC_STORE_PATH, STR, NULL); VAR(DCC_USE_GATEWAY_ADDR, BOOL, NULL) #define DEFAULT_DEBUG 0 VAR(DEBUG, INT, NULL); #define DEFAULT_DEFAULT_REALNAME NULL VAR(DEFAULT_REALNAME, STR, NULL); #define DEFAULT_DEFAULT_USERNAME NULL VAR(DEFAULT_USERNAME, STR, NULL); VAR(DISPATCH_UNKNOWN_COMMANDS, BOOL, NULL); VAR(DISPLAY, BOOL, NULL); VAR(DO_NOTIFY_IMMEDIATELY, BOOL, NULL); VAR(FLOATING_POINT_MATH, BOOL, NULL); VAR(FLOATING_POINT_PRECISION, INT, NULL); VAR(FLOOD_AFTER, INT, NULL); VAR(FLOOD_IGNORE, BOOL, NULL); VAR(FLOOD_MASKUSER, INT, NULL); VAR(FLOOD_RATE, INT, NULL); VAR(FLOOD_RATE_PER, INT, NULL); VAR(FLOOD_USERS, INT, NULL); VAR(FLOOD_WARNING, BOOL, NULL); VAR(HIDE_PRIVATE_CHANNELS, BOOL, update_all_status_wrapper); VAR(HOLD_SLIDER, INT, NULL); VAR(INDENT, BOOL, set_indent); VAR(INPUT_INDICATOR_LEFT, STR, NULL); VAR(INPUT_INDICATOR_RIGHT, STR, NULL); VAR(INPUT_PROMPT, STR, set_input_prompt); VAR(INSERT_MODE, BOOL, update_all_status_wrapper); VAR(KEY_INTERVAL, INT, set_key_interval); VAR(LASTLOG, INT, set_lastlog_size); VAR(LASTLOG_LEVEL, STR, set_lastlog_mask); VAR(LASTLOG_REWRITE, STR, NULL); #define DEFAULT_LOAD_PATH NULL VAR(LOAD_PATH, STR, NULL); VAR(LOG, BOOL, logger); VAR(LOGFILE, STR, NULL); #define DEFAULT_LOG_REWRITE NULL VAR(LOG_REWRITE, STR, NULL); VAR(MAIL, INT, set_mail); VAR(MAIL_INTERVAL, INT, set_mail_interval); VAR(MAIL_TYPE, STR, set_mail_type); #define DEFAULT_MANGLE_DISPLAY "NORMALIZE" VAR(MANGLE_DISPLAY, STR, set_mangle_display); #define DEFAULT_MANGLE_INBOUND NULL VAR(MANGLE_INBOUND, STR, set_mangle_inbound); #define DEFAULT_MANGLE_LOGFILES NULL VAR(MANGLE_LOGFILES, STR, set_mangle_logfiles); #define DEFAULT_MANGLE_OUTBOUND NULL VAR(MANGLE_OUTBOUND, STR, set_mangle_outbound); VAR(METRIC_TIME, BOOL, reset_clock); VAR(MIRC_BROKEN_DCC_RESUME, BOOL, NULL); VAR(MODE_STRIPPER, BOOL, NULL); VAR(NEW_SERVER_LASTLOG_LEVEL, STR, set_new_server_lastlog_mask); VAR(NOTIFY, BOOL, set_notify); VAR(NOTIFY_INTERVAL, INT, set_notify_interval); VAR(NOTIFY_LEVEL, STR, set_notify_mask); VAR(NOTIFY_ON_TERMINATION, BOOL, NULL); VAR(NOTIFY_USERHOST_AUTOMATIC, BOOL, NULL); VAR(NO_CONTROL_LOG, BOOL, NULL); /* XXX /set mangle_logfile */ VAR(NO_CTCP_FLOOD, BOOL, NULL); VAR(NO_FAIL_DISCONNECT, BOOL, NULL); VAR(OLD_MATH_PARSER, BOOL, NULL); VAR(OLD_SERVER_LASTLOG_LEVEL, STR, set_old_server_lastlog_mask); #define DEFAULT_OUTPUT_REWRITE NULL VAR(OUTPUT_REWRITE, STR, NULL); VAR(PAD_CHAR, CHAR, NULL); VAR(QUIT_MESSAGE, STR, NULL); VAR(RANDOM_SOURCE, INT, NULL); VAR(SCREEN_OPTIONS, STR, NULL); VAR(SCROLLBACK, INT, set_scrollback_size); VAR(SCROLLBACK_RATIO, INT, NULL); VAR(SCROLL_LINES, INT, set_scroll_lines); VAR(SHELL, STR, NULL); VAR(SHELL_FLAGS, STR, NULL); VAR(SHELL_LIMIT, INT, NULL); VAR(SHOW_CHANNEL_NAMES, BOOL, NULL); VAR(SHOW_NUMERICS, BOOL, NULL); VAR(SHOW_STATUS_ALL, BOOL, update_all_status_wrapper); VAR(SSL_ROOT_CERTS_LOCATION, STR, set_ssl_root_certs_location); VAR(STATUS_AWAY, STR, build_status); VAR(STATUS_CHANNEL, STR, build_status); VAR(STATUS_CHANOP, STR, build_status); VAR(STATUS_CLOCK, STR, build_status); VAR(STATUS_CPU_SAVER, STR, build_status); #define DEFAULT_STATUS_DOES_EXPANDOS 0 VAR(STATUS_DOES_EXPANDOS, BOOL, NULL); VAR(STATUS_FORMAT, STR, build_status); VAR(STATUS_FORMAT1, STR, build_status); VAR(STATUS_FORMAT2, STR, build_status); VAR(STATUS_HALFOP, STR, build_status); VAR(STATUS_HOLD, STR, build_status); VAR(STATUS_HOLD_LINES, STR, build_status); VAR(STATUS_HOLDMODE, STR, build_status); VAR(STATUS_INSERT, STR, build_status); VAR(STATUS_MAIL, STR, build_status); VAR(STATUS_MODE, STR, build_status); VAR(STATUS_NICKNAME, STR, build_status); VAR(STATUS_NOSWAP, STR, build_status); VAR(STATUS_NOTIFY, STR, build_status); VAR(STATUS_NO_REPEAT, BOOL, build_status); VAR(STATUS_OPER, STR, build_status); VAR(STATUS_OVERWRITE, STR, build_status); VAR(STATUS_QUERY, STR, build_status); VAR(STATUS_SCROLLBACK, STR, build_status); VAR(STATUS_SERVER, STR, build_status); VAR(STATUS_SSL_OFF, STR, build_status); VAR(STATUS_SSL_ON, STR, build_status); VAR(STATUS_UMODE, STR, build_status); VAR(STATUS_USER, STR, build_status); VAR(STATUS_USER1, STR, build_status); VAR(STATUS_USER10, STR, build_status); VAR(STATUS_USER11, STR, build_status); VAR(STATUS_USER12, STR, build_status); VAR(STATUS_USER13, STR, build_status); VAR(STATUS_USER14, STR, build_status); VAR(STATUS_USER15, STR, build_status); VAR(STATUS_USER16, STR, build_status); VAR(STATUS_USER17, STR, build_status); VAR(STATUS_USER18, STR, build_status); VAR(STATUS_USER19, STR, build_status); VAR(STATUS_USER2, STR, build_status); VAR(STATUS_USER20, STR, build_status); VAR(STATUS_USER21, STR, build_status); VAR(STATUS_USER22, STR, build_status); VAR(STATUS_USER23, STR, build_status); VAR(STATUS_USER24, STR, build_status); VAR(STATUS_USER25, STR, build_status); VAR(STATUS_USER26, STR, build_status); VAR(STATUS_USER27, STR, build_status); VAR(STATUS_USER28, STR, build_status); VAR(STATUS_USER29, STR, build_status); VAR(STATUS_USER3, STR, build_status); VAR(STATUS_USER30, STR, build_status); VAR(STATUS_USER31, STR, build_status); VAR(STATUS_USER32, STR, build_status); VAR(STATUS_USER33, STR, build_status); VAR(STATUS_USER34, STR, build_status); VAR(STATUS_USER35, STR, build_status); VAR(STATUS_USER36, STR, build_status); VAR(STATUS_USER37, STR, build_status); VAR(STATUS_USER38, STR, build_status); VAR(STATUS_USER39, STR, build_status); VAR(STATUS_USER4, STR, build_status); VAR(STATUS_USER5, STR, build_status); VAR(STATUS_USER6, STR, build_status); VAR(STATUS_USER7, STR, build_status); VAR(STATUS_USER8, STR, build_status); VAR(STATUS_USER9, STR, build_status); VAR(STATUS_VOICE, STR, build_status); VAR(STATUS_WINDOW, STR, build_status); VAR(SUPPRESS_FROM_REMOTE_SERVER, BOOL, NULL); VAR(SWITCH_CHANNELS_BETWEEN_WINDOWS, BOOL, NULL); VAR(TERM_DOES_BRIGHT_BLINK, BOOL, NULL); VAR(TMUX_OPTIONS, STR, NULL); VAR(USER_INFORMATION, STR, NULL); VAR(WORD_BREAK, STR, NULL); #define DEFAULT_WSERV_PATH WSERV_PATH VAR(WSERV_PATH, STR, NULL); VAR(WSERV_TYPE, STR, set_wserv_type); VAR(XTERM, STR, NULL); VAR(XTERM_OPTIONS, STR, NULL); }
// Helper function to // split the bucket in 'table' at address // 'address', growing table if necessary static void split_bucket(XtndblNHashTable *table, int address) { // FIRST, // check whether we need to grow the table or not if (table->buckets[address]->depth == table->depth && table->buckets[address]->nkeys == table->bucketsize) { // The keys that store in this bucket is full, we need to grow // the table double_extnd_table(table); } // SECOND // create a new bucket and update both buckets' depth Bucket *bucket = table->buckets[address]; int depth = bucket->depth; int first_address = bucket->id; int new_depth = depth + 1; bucket->depth = new_depth; // New bucket's first address will be a 1 bit plus the old first address int new_first_address = 1 << depth | first_address; Bucket *newbucket = new_bucket(new_first_address, new_depth, table->bucketsize); table->stats.nbuckets++; // THIRD, // redirect every second address pointing to this bucket to the new // bucket construct addresses by joining a bit 'prefix' and a bit // 'suffix' (defined below) // Suffix: a 1 bit followed by the previous bucket bit address int bit_address = rightmostnbits(depth, first_address); int suffix = (1 << depth) | bit_address; // Prefix: all bitstrings of length equal to the difference between the // new bucket depth and the table depth // Use a for loop to enumerate all possible prefixes less than maxprefix int maxprefix = 1 << (table->depth - new_depth); int prefix; for (prefix = 0; prefix < maxprefix; prefix++) { // Construct address by joining this prefix and the suffix int a = (prefix << new_depth) | suffix; // Redirect this table entry to point at the new bucket table->buckets[a] = newbucket; } // FINALLY, // Filter the key from the old bucket into its rightful place in the new // table (which may be the old bucket, or may be the new bucket) // Remove and reinsert the keys int64 *keys = bucket->keys; int i, total_keys = bucket->nkeys; bucket->nkeys = 0; for (i = 0; i < total_keys; i++) { reinsert_key(table, keys[i]); } }