00001
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <pthread.h>
00011 #include <unistd.h>
00012 #include <stddef.h>
00013 #include <misc/result.h>
00014 #include <misc/malloc.h>
00015 #include <misc/pool.h>
00016 #include <misc/debug.h>
00017 #include <misc/mutex.h>
00018 #include <core/config.h>
00019
00020 struct txc_pool_object_s {
00021 void *buf;
00022 char status;
00023 struct txc_pool_object_s *next;
00024 struct txc_pool_object_s *prev;
00025 };
00026
00027 struct txc_pool_s {
00028 txc_mutex_t mutex;
00029 void *full_buf;
00030 txc_pool_object_t *obj_list;
00031 txc_pool_object_t *obj_free_head;
00032 txc_pool_object_t *obj_allocated_head;
00033 unsigned int obj_free_num;
00034 unsigned int obj_allocated_num;
00035 unsigned int obj_size;
00036 unsigned int obj_num;
00037 txc_pool_object_constructor_t obj_constructor;
00038 };
00039
00040
00041 txc_result_t
00042 txc_pool_create(txc_pool_t **poolp,
00043 unsigned int obj_size,
00044 unsigned int obj_num,
00045 txc_pool_object_constructor_t obj_constructor)
00046 {
00047 txc_pool_object_t *object_list;
00048 char *buf;
00049 int i;
00050
00051 *poolp = (txc_pool_t *) MALLOC(sizeof(txc_pool_t));
00052 if (*poolp == NULL) {
00053 return TXC_R_NOMEMORY;
00054 }
00055 (*poolp)->obj_size = obj_size;
00056 (*poolp)->obj_num = obj_num;
00057 object_list = (txc_pool_object_t *) CALLOC(obj_num,
00058 sizeof(txc_pool_object_t));
00059 if (object_list == NULL) {
00060 FREE(*poolp);
00061 return TXC_R_NOMEMORY;
00062 }
00063 (*poolp)->obj_list = object_list;
00064 if ((buf = CALLOC(obj_num, obj_size)) == NULL) {
00065 FREE(object_list);
00066 FREE(*poolp);
00067 return TXC_R_NOMEMORY;
00068 }
00069 (*poolp)->full_buf = buf;
00070 for (i=0;i<obj_num;i++) {
00071 object_list[i].buf = &buf[i*obj_size];
00072 object_list[i].next = &object_list[(i+1)%obj_num];
00073 object_list[i].prev = &object_list[(i-1)%obj_num];
00074 object_list[i].status = TXC_POOL_OBJECT_FREE;
00075 if (obj_constructor != NULL) {
00076 obj_constructor(object_list[i].buf);
00077 }
00078 }
00079 object_list[0].prev = object_list[obj_num-1].next = NULL;
00080 (*poolp)->obj_free_num = obj_num;
00081 (*poolp)->obj_free_head = &object_list[0];
00082 (*poolp)->obj_allocated_num = 0;
00083 (*poolp)->obj_allocated_head = NULL;
00084 if (TXC_MUTEX_INIT(&((*poolp)->mutex), NULL) !=0) {
00085 FREE(buf);
00086 FREE(object_list);
00087 FREE(*poolp);
00088 return TXC_R_NOTINITLOCK;
00089 }
00090 return TXC_R_SUCCESS;
00091 }
00092
00093
00094 txc_result_t
00095 txc_pool_destroy(txc_pool_t **poolp)
00096 {
00097 TXC_ASSERT(*poolp != NULL);
00098 FREE((*poolp)->full_buf);
00099 FREE((*poolp)->obj_list);
00100 FREE(*poolp);
00101 *poolp = NULL;
00102 return TXC_R_SUCCESS;
00103 }
00104
00105
00106 txc_result_t
00107 txc_pool_object_alloc(txc_pool_t *pool, void **objp, int lock)
00108 {
00109 txc_result_t result;
00110 txc_pool_object_t *pool_object;
00111
00112 if (lock) {
00113 TXC_MUTEX_LOCK(&pool->mutex);
00114 }
00115 if (pool->obj_free_num == 0) {
00116 *objp = NULL;
00117 result = TXC_R_NOMEMORY;
00118 goto unlock;
00119 }
00120 pool_object = pool->obj_free_head;
00121 pool->obj_free_head = pool_object->next;
00122 if (pool->obj_free_head) {
00123 pool->obj_free_head->prev = NULL;
00124 }
00125 pool_object->prev = NULL;
00126 pool_object->next = pool->obj_allocated_head;
00127 if (pool->obj_allocated_head) {
00128 pool->obj_allocated_head->prev = pool_object;
00129 }
00130 pool->obj_allocated_head = pool_object;
00131 pool->obj_allocated_num++;
00132 pool->obj_free_num--;
00133 *objp = pool_object->buf;
00134 pool_object->status = TXC_POOL_OBJECT_ALLOCATED;
00135 result = TXC_R_SUCCESS;
00136 unlock:
00137 if (lock) {
00138 TXC_MUTEX_UNLOCK(&pool->mutex);
00139 }
00140 return result;
00141 }
00142
00143
00144 void
00145 txc_pool_object_free(txc_pool_t *pool, void **objp, int lock)
00146 {
00147 txc_pool_object_t *pool_object;
00148 unsigned int index;
00149
00150 TXC_ASSERT(pool);
00151 TXC_ASSERT(*objp);
00152 if (lock) {
00153 TXC_MUTEX_LOCK(&(pool->mutex));
00154 }
00155 index = ((unsigned int) ( (char*) *objp - (char*) pool->full_buf)) / pool->obj_size;
00156 pool_object = &pool->obj_list[index];
00157 TXC_ASSERT(pool_object->status == TXC_POOL_OBJECT_ALLOCATED);
00158 if (pool_object->prev) {
00159 pool_object->prev->next = pool_object->next;
00160 } else {
00161 pool->obj_allocated_head = pool_object->next;
00162 }
00163 if (pool_object->next) {
00164 pool_object->next->prev = pool_object->prev;
00165 }
00166 pool_object->next = pool->obj_free_head;
00167 pool_object->prev = NULL;
00168 if (pool->obj_free_head) {
00169 pool->obj_free_head->prev = pool_object;
00170 }
00171 pool->obj_allocated_num--;
00172 pool->obj_free_num++;
00173 pool_object->status = TXC_POOL_OBJECT_FREE;
00174 pool->obj_free_head = pool_object;
00175 if (lock) {
00176 TXC_MUTEX_UNLOCK(&(pool->mutex));
00177 }
00178 *objp = NULL;
00179 }
00180
00181
00182 txc_pool_object_t *
00183 txc_pool_object_first(txc_pool_t *pool, int obj_status)
00184 {
00185 switch (obj_status) {
00186 case TXC_POOL_OBJECT_FREE:
00187 return pool->obj_free_head;
00188 case TXC_POOL_OBJECT_ALLOCATED:
00189 return pool->obj_allocated_head;
00190 case TXC_POOL_OBJECT_ALLOCATED & TXC_POOL_OBJECT_FREE:
00191 return pool->obj_list;
00192 default:
00193 TXC_INTERNALERROR("Unknown status of pool object");
00194 }
00195 return NULL;
00196 }
00197
00198
00199 txc_pool_object_t *
00200 txc_pool_object_next(txc_pool_object_t *obj)
00201 {
00202 return obj->next;
00203 }
00204
00205
00206 void *
00207 txc_pool_object_of(txc_pool_object_t *obj)
00208 {
00209 return obj->buf;
00210 }
00211
00212 void
00213 txc_pool_lock(txc_pool_t *pool)
00214 {
00215 TXC_MUTEX_LOCK(&pool->mutex);
00216 }
00217
00218
00219 void
00220 txc_pool_unlock(txc_pool_t *pool)
00221 {
00222 TXC_MUTEX_UNLOCK(&pool->mutex);
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 void
00236 txc_pool_print(txc_pool_t *pool, txc_pool_object_print_t printer, int verbose)
00237 {
00238 txc_pool_object_t *pool_object;
00239 unsigned int index;
00240
00241 if (TXC_DEBUG_POOL) {
00242 TXC_MUTEX_LOCK(&(pool->mutex));
00243 fprintf(TXC_DEBUG_OUT, "FREE POOL\n");
00244 pool_object = pool->obj_free_head;
00245 while (pool_object) {
00246 index = (pool_object - pool->obj_list);
00247 if (verbose) {
00248 fprintf(TXC_DEBUG_OUT, "Object Index = %u\t", index);
00249 if (pool_object->prev) {
00250 index = (pool_object->prev - pool->obj_list);
00251 fprintf(TXC_DEBUG_OUT, "[prev = %u, ", index);
00252 } else {
00253 fprintf(TXC_DEBUG_OUT, "[prev = NULL, ");
00254 }
00255 if (pool_object->next) {
00256 index = (pool_object->next - pool->obj_list);
00257 fprintf(TXC_DEBUG_OUT, "next = %u]\n", index);
00258 } else {
00259 fprintf(TXC_DEBUG_OUT, "next = NULL]\n");
00260 }
00261 }
00262 if (printer) {
00263 printer(pool_object->buf);
00264 }
00265 pool_object = pool_object->next;
00266 }
00267 fprintf(TXC_DEBUG_OUT, "\nALLOCATED POOL\n");
00268 pool_object = pool->obj_allocated_head;
00269 while (pool_object) {
00270 index = (pool_object - pool->obj_list);
00271 if (verbose) {
00272 fprintf(TXC_DEBUG_OUT, "Object Index = %u\t", index);
00273 if (pool_object->prev) {
00274 index = (pool_object->prev - pool->obj_list);
00275 fprintf(TXC_DEBUG_OUT, "[prev = %u, ", index);
00276 } else {
00277 fprintf(TXC_DEBUG_OUT, "[prev = NULL, ");
00278 }
00279 if (pool_object->next) {
00280 index = (pool_object->next - pool->obj_list);
00281 fprintf(TXC_DEBUG_OUT, "next = %u]\n", index);
00282 } else {
00283 fprintf(TXC_DEBUG_OUT, "next = NULL]\n");
00284 }
00285 }
00286 if (printer) {
00287 printer(pool_object->buf);
00288 }
00289 pool_object = pool_object->next;
00290 }
00291 TXC_MUTEX_UNLOCK(&(pool->mutex));
00292 }
00293 }