X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fzn_malloc.c;h=ad46d96e660c00095bcba21b0b06a5381e8326ab;hb=3cdba151ad18dba10786fde4464442ddaf67b5fe;hp=31c21dd84a29dd94dd5bf8563de3e4c9965ffe74;hpb=10f8eae366722896040ce51f81acae1a95af08c9;p=openldap diff --git a/servers/slapd/zn_malloc.c b/servers/slapd/zn_malloc.c index 31c21dd84a..ad46d96e66 100644 --- a/servers/slapd/zn_malloc.c +++ b/servers/slapd/zn_malloc.c @@ -2,7 +2,7 @@ /* $OpenLDAP$*/ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2004 The OpenLDAP Foundation. + * Copyright 2003-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -13,15 +13,15 @@ * top-level directory of the distribution or, alternatively, at * . */ -/* Copyright 2004 IBM Corporation +/* Portions Copyright 2004 IBM Corporation * All rights reserved. - * Redisribution and use in source and binary forms, with or without - * modification, are permitted only as authorizd by the OpenLADP + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP * Public License. */ /* ACKNOWLEDGEMENTS - * This work originally developed by Jong-Hyuk Choi - * 2004/12/09 jongchoi@OpenLDAP.org + * This work originally developed by Jong-Hyuk Choi for inclusion in + * OpenLDAP Software. */ #include "portable.h" @@ -29,13 +29,14 @@ #include #include #include -#include #include #include "slap.h" #ifdef SLAP_ZONE_ALLOC +#include + static int slap_zone_cmp(const void *v1, const void *v2); void * slap_replenish_zopool(void *ctx); @@ -62,26 +63,29 @@ slap_zn_mem_destroy( } while (pad_shift >>= 1); ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); - for (i = 0; i <= zh->zh_zoneorder - order_start; i++) { + for (i = 0; i < zh->zh_zoneorder - order_start + 1; i++) { zo = LDAP_LIST_FIRST(&zh->zh_free[i]); while (zo) { struct zone_object *zo_tmp = zo; zo = LDAP_LIST_NEXT(zo, zo_link); + LDAP_LIST_REMOVE(zo_tmp, zo_link); LDAP_LIST_INSERT_HEAD(&zh->zh_zopool, zo_tmp, zo_link); } } ch_free(zh->zh_free); for (i = 0; i < zh->zh_numzones; i++) { - for (j = 0; j < zh->zh_zoneorder - order_start; j++) { + for (j = 0; j < zh->zh_zoneorder - order_start + 1; j++) { ch_free(zh->zh_maps[i][j]); } ch_free(zh->zh_maps[i]); munmap(zh->zh_zones[i], zh->zh_zonesize); + ldap_pvt_thread_rdwr_destroy(&zh->zh_znlock[i]); } ch_free(zh->zh_maps); ch_free(zh->zh_zones); ch_free(zh->zh_seqno); + ch_free(zh->zh_znlock); avl_free(zh->zh_zonetree, slap_zo_release); @@ -99,8 +103,9 @@ slap_zn_mem_destroy( zo = LDAP_LIST_NEXT(zo, zo_link); ch_free(zo_tmp); } - ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); - ldap_pvt_thread_mutex_destroy( &zh->zh_mutex ); + ldap_pvt_thread_mutex_unlock(&zh->zh_mutex); + ldap_pvt_thread_rdwr_destroy(&zh->zh_lock); + ldap_pvt_thread_mutex_destroy(&zh->zh_mutex); ch_free(zh); } @@ -165,6 +170,8 @@ slap_zn_mem_create( order = order_end - order_start + 1; zh->zh_zones = (void **)ch_malloc(zh->zh_maxzones * sizeof(void*)); + zh->zh_znlock = (ldap_pvt_thread_rdwr_t *)ch_malloc( + zh->zh_maxzones * sizeof(ldap_pvt_thread_rdwr_t *)); zh->zh_maps = (unsigned char ***)ch_malloc( zh->zh_maxzones * sizeof(unsigned char**)); @@ -187,7 +194,7 @@ slap_zn_mem_create( int shiftamt = order_start + 1 + j; int nummaps = zh->zh_zonesize >> shiftamt; assert(nummaps); - nummaps /= 8; + nummaps >>= 3; if (!nummaps) nummaps = 1; zh->zh_maps[i][j] = (unsigned char *)ch_malloc(nummaps); memset(zh->zh_maps[i][j], 0, nummaps); @@ -211,9 +218,12 @@ slap_zn_mem_create( zo->zo_siz = zh->zh_zonesize; zo->zo_idx = i; avl_insert(&zh->zh_zonetree, zo, slap_zone_cmp, avl_dup_error); + ldap_pvt_thread_rdwr_init(&zh->zh_znlock[i]); } + LDAP_STAILQ_INIT(&zh->zh_latency_history_queue); ldap_pvt_thread_mutex_init(&zh->zh_mutex); + ldap_pvt_thread_rdwr_init(&zh->zh_lock); return zh; } @@ -337,7 +347,7 @@ retry: int shiftamt = order_start + 1 + j; int nummaps = zh->zh_zonesize >> shiftamt; assert(nummaps); - nummaps /= 8; + nummaps >>= 3; if (!nummaps) nummaps = 1; zh->zh_maps[i][j] = (unsigned char *)ch_malloc(nummaps); memset(zh->zh_maps[i][j], 0, nummaps); @@ -362,6 +372,7 @@ retry: zo->zo_siz = zh->zh_zonesize; zo->zo_idx = i; avl_insert(&zh->zh_zonetree, zo, slap_zone_cmp, avl_dup_error); + ldap_pvt_thread_rdwr_init(&zh->zh_znlock[i]); } zh->zh_numzones += zh->zh_deltazones; ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); @@ -520,6 +531,7 @@ slap_zn_free(void *ptr, void *ctx) zo = LDAP_LIST_FIRST(&zh->zh_zopool); LDAP_LIST_REMOVE(zo, zo_link); zo->zo_ptr = tmpp; + zo->zo_idx = idx; Debug(LDAP_DEBUG_NONE, "slap_zn_free: merging 0x%x\n", zo->zo_ptr, 0, 0); @@ -530,7 +542,7 @@ slap_zn_free(void *ptr, void *ctx) Debug(LDAP_DEBUG_ANY, "slap_zn_free: " "free object not found while bit is clear.\n", 0, 0, 0); - assert(zo); + assert(zo != NULL); } } else { @@ -541,6 +553,7 @@ slap_zn_free(void *ptr, void *ctx) zo = LDAP_LIST_FIRST(&zh->zh_zopool); LDAP_LIST_REMOVE(zo, zo_link); zo->zo_ptr = tmpp; + zo->zo_idx = idx; Debug(LDAP_DEBUG_NONE, "slap_zn_free: merging 0x%x\n", zo->zo_ptr, 0, 0); @@ -580,6 +593,7 @@ slap_zn_free(void *ptr, void *ctx) zo = LDAP_LIST_FIRST(&zh->zh_zopool); LDAP_LIST_REMOVE(zo, zo_link); zo->zo_ptr = tmpp; + zo->zo_idx = idx; Debug(LDAP_DEBUG_NONE, "slap_zn_free: merging 0x%x\n", zo->zo_ptr, 0, 0); @@ -590,7 +604,7 @@ slap_zn_free(void *ptr, void *ctx) Debug(LDAP_DEBUG_ANY, "slap_zn_free: " "free object not found while bit is clear.\n", 0, 0, 0 ); - assert( zo ); + assert(zo != NULL); } } else { @@ -601,6 +615,7 @@ slap_zn_free(void *ptr, void *ctx) zo = LDAP_LIST_FIRST(&zh->zh_zopool); LDAP_LIST_REMOVE(zo, zo_link); zo->zo_ptr = tmpp; + zo->zo_idx = idx; Debug(LDAP_DEBUG_NONE, "slap_zn_free: merging 0x%x\n", zo->zo_ptr, 0, 0); @@ -656,4 +671,302 @@ slap_replenish_zopool( return zo_block; } + +int +slap_zn_invalidate( + void *ctx, + void *ptr +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int seqno = *((ber_len_t*)ptr - 2); + int idx = -1, rc = 0; + int pad = 2*sizeof(int)-1, pad_shift; + int order_start = -1, i; + struct zone_object *zo; + + pad_shift = pad - 1; + do { + order_start++; + } while (pad_shift >>= 1); + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + madvise(zh->zh_zones[idx], zh->zh_zonesize, MADV_DONTNEED); + for (i = 0; i < zh->zh_zoneorder - order_start + 1; i++) { + int shiftamt = order_start + 1 + i; + int nummaps = zh->zh_zonesize >> shiftamt; + assert(nummaps); + nummaps >>= 3; + if (!nummaps) nummaps = 1; + memset(zh->zh_maps[idx][i], 0, nummaps); + zo = LDAP_LIST_FIRST(&zh->zh_free[i]); + while (zo) { + struct zone_object *zo_tmp = zo; + zo = LDAP_LIST_NEXT(zo, zo_link); + if (zo_tmp && zo_tmp->zo_idx == idx) { + LDAP_LIST_REMOVE(zo_tmp, zo_link); + LDAP_LIST_INSERT_HEAD(&zh->zh_zopool, zo_tmp, zo_link); + } + } + } + if (LDAP_LIST_EMPTY(&zh->zh_zopool)) { + slap_replenish_zopool(zh); + } + zo = LDAP_LIST_FIRST(&zh->zh_zopool); + LDAP_LIST_REMOVE(zo, zo_link); + zo->zo_ptr = zh->zh_zones[idx]; + zo->zo_idx = idx; + LDAP_LIST_INSERT_HEAD(&zh->zh_free[zh->zh_zoneorder-order_start], + zo, zo_link); + zh->zh_seqno[idx]++; + } else { + Debug(LDAP_DEBUG_NONE, "zone not found for (ctx=0x%x, ptr=0x%x) !\n", + ctx, ptr, 0); + } + + ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); + Debug(LDAP_DEBUG_NONE, "zone %d invalidate\n", idx, 0, 0); + return rc; +} + +int +slap_zn_validate( + void *ctx, + void *ptr, + int seqno +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int idx, rc = 0; + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + assert(seqno <= zh->zh_seqno[idx]); + rc = (seqno == zh->zh_seqno[idx]); + } + + return rc; +} + +int slap_zh_rlock( + void *ctx +) +{ + struct zone_heap* zh = ctx; + ldap_pvt_thread_rdwr_rlock(&zh->zh_lock); +} + +int slap_zh_runlock( + void *ctx +) +{ + struct zone_heap* zh = ctx; + ldap_pvt_thread_rdwr_runlock(&zh->zh_lock); +} + +int slap_zh_wlock( + void *ctx +) +{ + struct zone_heap* zh = ctx; + ldap_pvt_thread_rdwr_wlock(&zh->zh_lock); +} + +int slap_zh_wunlock( + void *ctx +) +{ + struct zone_heap* zh = ctx; + ldap_pvt_thread_rdwr_wunlock(&zh->zh_lock); +} + +int slap_zn_rlock( + void *ctx, + void *ptr +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int idx; + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + ldap_pvt_thread_rdwr_rlock(&zh->zh_znlock[idx]); + } +} + +int slap_zn_runlock( + void *ctx, + void *ptr +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int idx; + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + ldap_pvt_thread_rdwr_runlock(&zh->zh_znlock[idx]); + } +} + +int slap_zn_wlock( + void *ctx, + void *ptr +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int idx; + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + ldap_pvt_thread_rdwr_wlock(&zh->zh_znlock[idx]); + } +} + +int slap_zn_wunlock( + void *ctx, + void *ptr +) +{ + struct zone_heap* zh = ctx; + struct zone_object zoi, *zoo; + struct zone_heap *zone = NULL; + int idx; + + zoi.zo_ptr = ptr; + zoi.zo_idx = -1; + + ldap_pvt_thread_mutex_lock( &zh->zh_mutex ); + zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp); + ldap_pvt_thread_mutex_unlock( &zh->zh_mutex ); + + if (zoo) { + idx = zoo->zo_idx; + assert(idx != -1); + ldap_pvt_thread_rdwr_wunlock(&zh->zh_znlock[idx]); + } +} + +#define T_SEC_IN_USEC 1000000 + +static int +slap_timediff(struct timeval *tv_begin, struct timeval *tv_end) +{ + uint64_t t_begin, t_end, t_diff; + + t_begin = T_SEC_IN_USEC * tv_begin->tv_sec + tv_begin->tv_usec; + t_end = T_SEC_IN_USEC * tv_end->tv_sec + tv_end->tv_usec; + t_diff = t_end - t_begin; + + if ( t_diff < 0 ) + t_diff = 0; + + return (int)t_diff; +} + +void +slap_set_timing(struct timeval *tv_set) +{ + gettimeofday(tv_set, (struct timezone *)NULL); +} + +int +slap_measure_timing(struct timeval *tv_set, struct timeval *tv_measure) +{ + gettimeofday(tv_measure, (struct timezone *)NULL); + return(slap_timediff(tv_set, tv_measure)); +} + +#define EMA_WEIGHT 0.999000 +#define SLAP_ZN_LATENCY_HISTORY_QLEN 500 +int +slap_zn_latency_history(void* ctx, int ea_latency) +{ +/* TODO: monitor /proc/stat (swap) as well */ + struct zone_heap* zh = ctx; + double t_diff = 0.0; + + zh->zh_ema_latency = (double)ea_latency * (1.0 - EMA_WEIGHT) + + zh->zh_ema_latency * EMA_WEIGHT; + if (!zh->zh_swapping && zh->zh_ema_samples++ % 100 == 99) { + struct zone_latency_history *zlh_entry; + zlh_entry = ch_calloc(1, sizeof(struct zone_latency_history)); + zlh_entry->zlh_latency = zh->zh_ema_latency; + LDAP_STAILQ_INSERT_TAIL( + &zh->zh_latency_history_queue, zlh_entry, zlh_next); + zh->zh_latency_history_qlen++; + while (zh->zh_latency_history_qlen > SLAP_ZN_LATENCY_HISTORY_QLEN) { + struct zone_latency_history *zlh; + zlh = LDAP_STAILQ_FIRST(&zh->zh_latency_history_queue); + LDAP_STAILQ_REMOVE_HEAD( + &zh->zh_latency_history_queue, zlh_next); + zh->zh_latency_history_qlen--; + ch_free(zlh); + } + if (zh->zh_latency_history_qlen == SLAP_ZN_LATENCY_HISTORY_QLEN) { + struct zone_latency_history *zlh_first, *zlh_last; + zlh_first = LDAP_STAILQ_FIRST(&zh->zh_latency_history_queue); + zlh_last = LDAP_STAILQ_LAST(&zh->zh_latency_history_queue, + zone_latency_history, zlh_next); + t_diff = zlh_last->zlh_latency - zlh_first->zlh_latency; + } + if (t_diff >= 2000) { + zh->zh_latency_jump++; + } else { + zh->zh_latency_jump = 0; + } + if (zh->zh_latency_jump > 3) { + zh->zh_latency_jump = 0; + zh->zh_swapping = 1; + } + } + return zh->zh_swapping; +} #endif /* SLAP_ZONE_ALLOC */