localmemcache 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/src/lmc_hashtable.h CHANGED
@@ -5,6 +5,7 @@
5
5
  #ifndef _LMC_HASHTABLE_H_INCLUDED_
6
6
  #define _LMC_HASHTABLE_H_INCLUDED_
7
7
  #include "lmc_error.h"
8
+ #include "lmc_valloc.h"
8
9
 
9
10
  typedef size_t va_string_t;
10
11
  typedef size_t va_ht_hash_entry_t;
@@ -16,18 +17,25 @@ typedef struct {
16
17
  } ht_hash_entry_t;
17
18
 
18
19
  #define HT_BUCKETS 499
20
+ #define ITERATOR_P(n) int ((n)) (void *ctx, const char *key, const char *value)
19
21
 
20
22
  typedef size_t va_ht_hash_t;
21
23
  typedef struct {
22
24
  va_ht_hash_entry_t va_buckets[HT_BUCKETS];
23
25
  } ht_hash_t;
24
26
 
25
-
26
27
  va_ht_hash_t ht_hash_create(void *base, lmc_error_t *e);
27
- int ht_set(void *base, va_ht_hash_t va_ht, const char *key, const char *value,
28
- lmc_error_t* e);
29
- ht_hash_entry_t *ht_lookup(void *base, va_ht_hash_t va_ht, const char *key);
30
- char *ht_get(void *base, va_ht_hash_t ht, const char *key);
31
- int ht_delete(void *base, va_ht_hash_t va_ht, const char *key);
28
+ int ht_set(void *base, va_ht_hash_t va_ht, const char *key,
29
+ size_t n_key, const char *value, size_t n_value, lmc_error_t *e);
30
+ ht_hash_entry_t *ht_lookup(void *base, va_ht_hash_t va_ht, const char *key,
31
+ size_t n_key);
32
+ const char *ht_get(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key,
33
+ size_t *n_value);
34
+ int ht_delete(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key);
32
35
  int ht_hash_destroy(void *base, va_ht_hash_t ht);
36
+ int ht_hash_iterate(void *base, va_ht_hash_t ht, void *ctx, ITERATOR_P(iter));
37
+
38
+ int ht_check_memory(void *base, va_ht_hash_t va_ht);
39
+ int ht_redo(void *base, va_ht_hash_t va_ht, lmc_log_descriptor_t *l,
40
+ lmc_error_t *e);
33
41
  #endif
data/src/lmc_lock.c CHANGED
@@ -4,27 +4,41 @@
4
4
  #include <sys/stat.h>
5
5
  #include <errno.h>
6
6
  #include <string.h>
7
+ #include <sys/types.h>
8
+ #include <unistd.h>
7
9
  #include <time.h>
8
10
  #include "lmc_lock.h"
9
11
 
10
12
  int c_l(lmc_lock_t *l, lmc_error_t *e) {
11
- if (!l) { strncpy(e->error_str, "Semaphore not initialized", 1023); }
13
+ if (!l) {
14
+ lmc_handle_error_with_err_string("check_lock",
15
+ "Semaphore not initialized", "LocalMemCacheError", e);
16
+ }
12
17
  return l != NULL;
13
18
  }
14
19
 
15
-
16
-
17
20
  lmc_lock_t *lmc_lock_init(const char *namespace, int init, lmc_error_t *e) {
18
21
  lmc_lock_t *l = malloc(sizeof(lmc_lock_t));
19
22
  if (!l) return NULL;
20
23
  strncpy((char *)&l->namespace, namespace, 1023);
21
24
 
22
25
  lmc_handle_error((l->sem = sem_open(l->namespace, O_CREAT, 0600, init)) == NULL,
23
- "sem_open", e);
26
+ "sem_open", "LockError", e);
24
27
  if (!l->sem) { free(l); return NULL; }
25
28
  return l;
26
29
  }
27
30
 
31
+ int lmc_clear_namespace_lock(const char *namespace) {
32
+ lmc_error_t e;
33
+ lmc_lock_t *l = lmc_lock_init(namespace, 1, &e);
34
+ //printf("clear_namespace locks: %s %d\n", namespace, lmc_lock_get_value(l));
35
+ lmc_lock_repair(l);
36
+ //printf("AFTER clear_namespace locks: %s %d\n", namespace,
37
+ //lmc_lock_get_value(l));
38
+ free(l);
39
+ return 1;
40
+ }
41
+
28
42
  int lmc_is_locked(lmc_lock_t* l, lmc_error_t *e) {
29
43
  if (!c_l(l, e)) { return 0; }
30
44
  if (sem_trywait(l->sem) == -1) {
@@ -35,12 +49,27 @@ int lmc_is_locked(lmc_lock_t* l, lmc_error_t *e) {
35
49
  }
36
50
  }
37
51
 
38
- int lmc_is_lock_working(lmc_lock_t* l, lmc_error_t *e) {
39
- if (!c_l(l, e)) { return 0; }
52
+ int lmc_sem_timed_wait(lmc_lock_t* l) {
40
53
  struct timespec ts;
41
54
  clock_gettime(CLOCK_REALTIME, &ts);
55
+ #ifdef DO_TEST_CRASH
56
+ ts.tv_sec += 1;
57
+ #else
42
58
  ts.tv_sec += 2;
43
- if (sem_timedwait(l->sem, &ts) == -1) {
59
+ #endif
60
+ return sem_timedwait(l->sem, &ts);
61
+ }
62
+
63
+ int lmc_sem_timed_wait_mandatory(lmc_lock_t* l) {
64
+ struct timespec ts;
65
+ clock_gettime(CLOCK_REALTIME, &ts);
66
+ ts.tv_sec += 20;
67
+ return sem_timedwait(l->sem, &ts);
68
+ }
69
+
70
+ int lmc_is_lock_working(lmc_lock_t* l, lmc_error_t *e) {
71
+ if (!c_l(l, e)) { return 0; }
72
+ if (lmc_sem_timed_wait(l) == -1) {
44
73
  return 0;
45
74
  } else {
46
75
  sem_post(l->sem);
@@ -51,15 +80,44 @@ int lmc_is_lock_working(lmc_lock_t* l, lmc_error_t *e) {
51
80
  void lmc_lock_repair(lmc_lock_t *l) {
52
81
  int v;
53
82
  sem_getvalue(l->sem, &v);
54
- if (v == 0) { sem_post(l->sem); }
83
+ if (v == 0) {
84
+ sem_post(l->sem);
85
+ }
86
+ sem_getvalue(l->sem, &v);
87
+ while (v > 1) {
88
+ sem_wait(l->sem);
89
+ sem_getvalue(l->sem, &v);
90
+ }
91
+ }
92
+
93
+ int lmc_lock_get_value(lmc_lock_t* l) {
94
+ int v = 0;
55
95
  sem_getvalue(l->sem, &v);
56
- printf("value after repair: %d\n", v);
96
+ return v;
57
97
  }
58
98
 
59
99
  int lmc_lock_obtain(const char *where, lmc_lock_t* l, lmc_error_t *e) {
60
- return c_l(l,e) && lmc_handle_error(sem_wait(l->sem) == -1, "sem_wait", e);
100
+ if (!c_l(l,e)) { return 0; }
101
+ int r = lmc_sem_timed_wait(l);
102
+ if (r == -1 && errno == ETIMEDOUT) {
103
+ lmc_handle_error_with_err_string("sem_timedwait", strerror(errno),
104
+ "LockTimedOut", e);
105
+ return 0;
106
+ }
107
+ return lmc_handle_error(r, "sem_timedwait", "LockError", e);
108
+ }
109
+
110
+ int lmc_lock_obtain_mandatory(const char *where, lmc_lock_t* l, lmc_error_t *e) {
111
+ int r = lmc_sem_timed_wait_mandatory(l);
112
+ if (r == -1 && errno == ETIMEDOUT) {
113
+ lmc_handle_error_with_err_string("sem_timedwait", strerror(errno),
114
+ "LockTimedOut", e);
115
+ return 0;
116
+ }
117
+ return c_l(l,e) && lmc_handle_error(r, "sem_wait", "LockError", e);
61
118
  }
62
119
 
63
120
  int lmc_lock_release(const char *where, lmc_lock_t* l, lmc_error_t *e) {
64
- return c_l(l, e) && lmc_handle_error(sem_post(l->sem) == -1, "sem_post", e);
121
+ return c_l(l, e) && lmc_handle_error(sem_post(l->sem) == -1, "sem_post",
122
+ "LockError", e);
65
123
  }
data/src/lmc_lock.h CHANGED
@@ -14,9 +14,12 @@ typedef struct {
14
14
 
15
15
  lmc_lock_t *lmc_lock_init(const char *namespace, int init, lmc_error_t *e);
16
16
  int lmc_lock_obtain(const char *where, lmc_lock_t* l, lmc_error_t *e);
17
+ int lmc_lock_obtain_mandatory(const char *where, lmc_lock_t* l, lmc_error_t *e);
17
18
  int lmc_lock_release(const char *where, lmc_lock_t* l, lmc_error_t *e);
18
19
 
19
20
  int lmc_is_locked(lmc_lock_t* l, lmc_error_t *e);
20
21
  int lmc_is_lock_working(lmc_lock_t* l, lmc_error_t *e);
21
22
  void lmc_lock_repair(lmc_lock_t *l);
23
+ int lmc_lock_get_value(lmc_lock_t* l);
24
+ int lmc_clear_namespace_lock(const char *namespace);
22
25
  #endif
data/src/lmc_shm.c CHANGED
@@ -20,6 +20,12 @@ int lmc_does_file_exist(const char *fn) {
20
20
  return stat(fn, &st) != -1;
21
21
  }
22
22
 
23
+ int lmc_file_size(const char *fn) {
24
+ struct stat st;
25
+ if (stat(fn, &st) == -1) return 0;
26
+ return st.st_size;
27
+ }
28
+
23
29
  void lmc_shm_ensure_root_path() {
24
30
  if (!lmc_does_file_exist(LMC_SHM_ROOT_PATH)) {
25
31
  mkdir(LMC_SHM_ROOT_PATH, 01777);
@@ -36,12 +42,20 @@ int lmc_does_namespace_exist(const char *ns) {
36
42
  return lmc_does_file_exist(fn);
37
43
  }
38
44
 
45
+ int lmc_namespace_size(const char *ns) {
46
+ char fn[1024];
47
+ lmc_file_path_for_namespace((char *)&fn, ns);
48
+ if (!lmc_does_file_exist(fn)) { return 0; }
49
+ return lmc_file_size(fn);
50
+ }
51
+
39
52
  int lmc_clean_namespace(const char *ns, lmc_error_t *e) {
40
53
  lmc_shm_ensure_root_path();
41
54
  char fn[1024];
42
55
  lmc_file_path_for_namespace((char *)&fn, ns);
43
56
  if (lmc_does_namespace_exist(ns)) {
44
- if (!lmc_handle_error(unlink(fn) == -1, "unlink", e)) { return 0; }
57
+ if (!lmc_handle_error(unlink(fn) == -1, "unlink", "ShmError",
58
+ e)) { return 0; }
45
59
  }
46
60
  return 1;
47
61
  }
@@ -57,7 +71,7 @@ lmc_shm_t *lmc_shm_create(const char* namespace, size_t size, int use_persistenc
57
71
  lmc_error_t *e) {
58
72
  lmc_shm_t *mc = calloc(1, sizeof(lmc_shm_t));
59
73
  if (!mc) {
60
- lmc_handle_error_with_err_string("lmc_shm_create", "Out of memory", e);
74
+ STD_OUT_OF_MEMORY_ERROR("lmc_shm_create");
61
75
  return NULL;
62
76
  }
63
77
  strncpy((char *)&mc->namespace, namespace, 1023);
@@ -68,13 +82,15 @@ lmc_shm_t *lmc_shm_create(const char* namespace, size_t size, int use_persistenc
68
82
  char fn[1024];
69
83
  lmc_file_path_for_namespace((char *)&fn, mc->namespace);
70
84
  if (!lmc_handle_error((mc->fd = open(fn, O_RDWR, (mode_t)0777)) == -1,
71
- "open", e)) goto open_failed;
72
- if (!lmc_handle_error(lseek(mc->fd, mc->size - 1, SEEK_SET) == -1, "lseek", e))
73
- goto failed;
74
- if (!lmc_handle_error(write(mc->fd, "", 1) != 1, "write", e)) goto failed;
85
+ "open", "ShmError", e)) goto open_failed;
86
+ if (!lmc_handle_error(lseek(mc->fd, mc->size - 1, SEEK_SET) == -1,
87
+ "lseek", "ShmError", e)) goto failed;
88
+ if (!lmc_handle_error(write(mc->fd, "", 1) != 1, "write",
89
+ "ShmError", e)) goto failed;
75
90
  mc->base = mmap(0, mc->size, PROT_READ | PROT_WRITE, MAP_SHARED, mc->fd,
76
91
  (off_t)0);
77
- if (!lmc_handle_error(mc->base == MAP_FAILED, "mmap", e)) goto failed;
92
+ if (!lmc_handle_error(mc->base == MAP_FAILED, "mmap", "ShmError", e))
93
+ goto failed;
78
94
  return mc;
79
95
 
80
96
  failed:
@@ -85,7 +101,8 @@ open_failed:
85
101
  }
86
102
 
87
103
  int lmc_shm_destroy(lmc_shm_t *mc, lmc_error_t *e) {
88
- int r = lmc_handle_error(munmap(mc->base, mc->size) == -1, "munmap", e);
104
+ int r = lmc_handle_error(munmap(mc->base, mc->size) == -1, "munmap",
105
+ "ShmError", e);
89
106
  close(mc->fd);
90
107
  free(mc);
91
108
  return r;
data/src/lmc_shm.h CHANGED
@@ -18,5 +18,6 @@ lmc_shm_t *lmc_shm_create(const char *namespace, size_t size, int use_persistenc
18
18
  lmc_error_t *e);
19
19
  int lmc_shm_destroy(lmc_shm_t *mc, lmc_error_t *e);
20
20
  int lmc_does_namespace_exist(const char *ns);
21
+ int lmc_namespace_size(const char *ns);
21
22
  int lmc_clean_namespace(const char *ns, lmc_error_t *e);
22
23
  #endif
data/src/lmc_valloc.c CHANGED
@@ -12,20 +12,17 @@
12
12
  #include <sys/mman.h>
13
13
 
14
14
  #include "lmc_valloc.h"
15
-
16
15
  #include "lmc_lock.h"
16
+ #include "lmc_common.h"
17
17
 
18
- typedef struct {
19
- size_t next;
20
- size_t size;
21
- } mem_chunk_descriptor_t;
18
+ #undef lmc_valloc
22
19
 
23
- mem_chunk_descriptor_t *md_first_free(void *base) {
24
- mem_descriptor_t *md = base;
20
+ lmc_mem_chunk_descriptor_t *md_first_free(void *base) {
21
+ lmc_mem_descriptor_t *md = base;
25
22
  return md->first_free == 0 ? 0 : base + md->first_free;
26
23
  }
27
24
 
28
- void lmc_dump_chunk(void *base, mem_chunk_descriptor_t* c) {
25
+ void lmc_dump_chunk(void *base, lmc_mem_chunk_descriptor_t* c) {
29
26
  size_t va_c = (void *)c - base;
30
27
  printf("chunk %zd:\n"
31
28
  " start: %zd\n"
@@ -36,7 +33,7 @@ void lmc_dump_chunk(void *base, mem_chunk_descriptor_t* c) {
36
33
  , va_c, va_c, va_c + c->size, c->size, c->next);
37
34
  }
38
35
 
39
- void lmc_dump_chunk_brief(char *who, void *base, mem_chunk_descriptor_t* c) {
36
+ void lmc_dump_chunk_brief(char *who, void *base, lmc_mem_chunk_descriptor_t* c) {
40
37
  if (!c) { return; }
41
38
  size_t va_c = (void *)c - base;
42
39
  printf("[%s] chunk %zd:\n", who, va_c);
@@ -44,7 +41,7 @@ void lmc_dump_chunk_brief(char *who, void *base, mem_chunk_descriptor_t* c) {
44
41
 
45
42
 
46
43
  void lmc_dump(void *base) {
47
- mem_chunk_descriptor_t* c = md_first_free(base);
44
+ lmc_mem_chunk_descriptor_t* c = md_first_free(base);
48
45
  size_t free = 0;
49
46
  long chunks = 0;
50
47
  while (c) {
@@ -55,22 +52,23 @@ void lmc_dump(void *base) {
55
52
  }
56
53
  }
57
54
 
58
- int is_va_valid(void *base, size_t va) {
59
- mem_descriptor_t *md = base;
60
- mem_chunk_descriptor_t* c = base + va;
61
- return !(((void *)c < base ) || (base + md->total_size + sizeof(mem_descriptor_t)) < (void *)c);
55
+ int lmc_is_va_valid(void *base, size_t va) {
56
+ lmc_mem_descriptor_t *md = base;
57
+ lmc_mem_chunk_descriptor_t* c = base + va;
58
+ return !(((void *)c < base ) ||
59
+ (base + md->total_size + sizeof(lmc_mem_descriptor_t)) < (void *)c);
62
60
  }
63
61
 
64
- mem_status_t lmc_status(void *base, char *where) {
65
- mem_descriptor_t *md = base;
66
- mem_chunk_descriptor_t* c = md_first_free(base);
67
- mem_status_t ms;
62
+ lmc_mem_status_t lmc_status(void *base, char *where) {
63
+ lmc_mem_descriptor_t *md = base;
64
+ lmc_mem_chunk_descriptor_t* c = md_first_free(base);
65
+ lmc_mem_status_t ms;
68
66
  size_t free = 0;
69
67
  size_t largest_chunk = 0;
70
68
  long chunks = 0;
71
69
  ms.total_mem = md->total_size;
72
70
  while (c) {
73
- if (!is_va_valid(base, (void *)c - base)) {
71
+ if (!lmc_is_va_valid(base, (void *)c - base)) {
74
72
  printf("[%s] invalid pointer detected: %ld...\n", where, (void *)c - base);
75
73
  lmc_dump(base);
76
74
  abort();
@@ -88,13 +86,13 @@ mem_status_t lmc_status(void *base, char *where) {
88
86
  }
89
87
 
90
88
  void lmc_show_status(void *base) {
91
- mem_status_t ms = lmc_status(base, "lmc_ss");
89
+ lmc_mem_status_t ms = lmc_status(base, "lmc_ss");
92
90
  printf("total: %zu\n", ms.total_mem);
93
91
  printf("chunks: %zu, free: %zu\n", ms.free_chunks, ms.free_mem);
94
92
  }
95
93
 
96
94
  int is_lmc_already_initialized(void *base) {
97
- mem_descriptor_t *md = base;
95
+ lmc_mem_descriptor_t *md = base;
98
96
  if (md->magic == 0xF00D) {
99
97
  #ifdef LMC_DEBUG_ALLOC
100
98
  printf("memory already initialized, skipping...\n");
@@ -105,14 +103,14 @@ int is_lmc_already_initialized(void *base) {
105
103
  }
106
104
 
107
105
  void lmc_init_memory(void *ptr, size_t size) {
108
- mem_descriptor_t *md = ptr;
109
- size_t s = size - sizeof(mem_descriptor_t);
110
- // size: enough space for mem_descriptor_t + mem_chunk_descriptor_t
111
- md->first_free = sizeof(mem_descriptor_t);
106
+ lmc_mem_descriptor_t *md = ptr;
107
+ size_t s = size - sizeof(lmc_mem_descriptor_t);
108
+ // size: enough space for lmc_mem_descriptor_t + lmc_mem_chunk_descriptor_t
109
+ md->first_free = sizeof(lmc_mem_descriptor_t);
112
110
  md->magic = 0xF00D;
113
111
  md->locked = 0;
114
112
  md->total_size = s;
115
- mem_chunk_descriptor_t *c = ptr + sizeof(mem_descriptor_t);
113
+ lmc_mem_chunk_descriptor_t *c = ptr + sizeof(lmc_mem_descriptor_t);
116
114
  c->next = 0;
117
115
  c->size = s;
118
116
  }
@@ -121,7 +119,7 @@ size_t lmc_max(size_t a, size_t b) {
121
119
  return a > b ? a : b;
122
120
  }
123
121
 
124
- size_t __s(char *where, mem_status_t ms, size_t mem_before, size_t expected_diff) {
122
+ size_t __s(char *where, lmc_mem_status_t ms, size_t mem_before, size_t expected_diff) {
125
123
  size_t free = ms.total_free_mem;
126
124
  printf("(%s) ", where);
127
125
  if (mem_before) { printf("[%ld:%zd] ", free - mem_before, expected_diff); }
@@ -135,15 +133,15 @@ size_t __s(char *where, mem_status_t ms, size_t mem_before, size_t expected_diff
135
133
  }
136
134
 
137
135
  size_t lmc_valloc(void *base, size_t size) {
138
- mem_descriptor_t *md = base;
139
- // MOD by power of 2
136
+ lmc_mem_descriptor_t *md = base;
137
+ // idea: MOD by power of 2
140
138
  size_t s = lmc_max(size + sizeof(size_t),
141
- sizeof(mem_chunk_descriptor_t) + sizeof(size_t));
139
+ sizeof(lmc_mem_chunk_descriptor_t) + sizeof(size_t));
142
140
  // larger than available space?
143
- mem_chunk_descriptor_t *c = md_first_free(base);
144
- mem_chunk_descriptor_t *p = NULL;
141
+ lmc_mem_chunk_descriptor_t *c = md_first_free(base);
142
+ lmc_mem_chunk_descriptor_t *p = NULL;
145
143
  if (size == 0) { return 0; }
146
- while (c && c->size <s ) {
144
+ while (c && c->size < s ) {
147
145
  p = c;
148
146
  if (c->next == 0) {
149
147
  c = 0;
@@ -156,13 +154,14 @@ size_t lmc_valloc(void *base, size_t size) {
156
154
  return 0;
157
155
  }
158
156
  size_t r = 0;
159
- if (c->size - s < sizeof(mem_chunk_descriptor_t)) { s = c->size; }
157
+ if (c->size - s < sizeof(lmc_mem_chunk_descriptor_t)) { s = c->size; }
160
158
  // ----------------- -------------------
161
159
  // | chunk | wanted: | |
162
160
  // ----------------- -------------------
163
161
  if (c->size == s) {
164
162
  if (p) { p->next = c->next; }
165
163
  else {md->first_free = c->next; }
164
+ LMC_TEST_CRASH
166
165
  r = (size_t)((void*)c - (void*)base);
167
166
  } else {
168
167
  // ----------------- -------------------
@@ -170,6 +169,7 @@ size_t lmc_valloc(void *base, size_t size) {
170
169
  // | | -------------------
171
170
  // -----------------
172
171
  c->size -= s;
172
+ LMC_TEST_CRASH
173
173
  r = (size_t)((void*)c - base) + c->size;
174
174
  }
175
175
  *(size_t *)(r + base) = s;
@@ -178,12 +178,12 @@ size_t lmc_valloc(void *base, size_t size) {
178
178
 
179
179
  // compact_chunks,
180
180
  void lmc_check_coalesce(void *base, size_t va_chunk) {
181
- mem_descriptor_t *md = base;
182
- mem_chunk_descriptor_t *chunk = base + va_chunk;
181
+ lmc_mem_descriptor_t *md = base;
182
+ lmc_mem_chunk_descriptor_t *chunk = base + va_chunk;
183
183
  size_t c_size = chunk->size;
184
184
  size_t va_chunk_p = 0;
185
185
  size_t va_c_free_chunk = 0;
186
- mem_chunk_descriptor_t* c_free_chunk = base + va_c_free_chunk;
186
+ lmc_mem_chunk_descriptor_t* c_free_chunk = base + va_c_free_chunk;
187
187
  size_t va_previous = 0;
188
188
  size_t merge1_chunk = 0;
189
189
  int merge1 = 0;
@@ -208,9 +208,13 @@ void lmc_check_coalesce(void *base, size_t va_chunk) {
208
208
  // ----------------------
209
209
  if (va_chunk + c_size == va_c_free_chunk) {
210
210
  chunk->size += c_free_chunk->size;
211
+ LMC_TEST_CRASH
211
212
  if (chunk->next == va_c_free_chunk) { va_previous = va_chunk; }
212
- mem_chunk_descriptor_t *p = va_previous ? base + va_previous : 0;
213
+ LMC_TEST_CRASH
214
+ lmc_mem_chunk_descriptor_t *p = va_previous ? base + va_previous : 0;
215
+ LMC_TEST_CRASH
213
216
  if (p) { p->next = c_free_chunk->next; }
217
+ LMC_TEST_CRASH
214
218
  break;
215
219
  }
216
220
  }
@@ -226,42 +230,33 @@ void lmc_check_coalesce(void *base, size_t va_chunk) {
226
230
  // | chunk |
227
231
  // ----------------------
228
232
  if (merge1) {
229
- mem_chunk_descriptor_t *cd = base + merge1_chunk;
230
- mem_chunk_descriptor_t *p = va_chunk_p ? base + va_chunk_p : 0;
231
- mem_chunk_descriptor_t *vacd = va_chunk? base + va_chunk : 0;
233
+ lmc_mem_chunk_descriptor_t *cd = base + merge1_chunk;
234
+ lmc_mem_chunk_descriptor_t *p = va_chunk_p ? base + va_chunk_p : 0;
235
+ lmc_mem_chunk_descriptor_t *vacd = va_chunk? base + va_chunk : 0;
236
+ LMC_TEST_CRASH
232
237
  if (p) { p->next = vacd->next; }
238
+ LMC_TEST_CRASH
233
239
  if (md->first_free == va_chunk) { md->first_free = chunk->next; }
240
+ LMC_TEST_CRASH
234
241
  cd->size += c_size;
235
242
  }
236
243
  }
237
244
 
238
-
239
- void lmc_free(void *base, size_t chunk) {
240
- #ifdef LMC_DEBUG_ALLOC
241
- size_t mb = __s("free1", lmc_status(base, "lmc_free1"), 0, 0);
242
- #endif
243
- if (chunk == 0) { return; }
244
- mem_descriptor_t *md = base;
245
- size_t va_used_chunk = chunk - sizeof(size_t);
245
+ void __lmc_free(void *base, size_t va_used_chunk, size_t uc_size) {
246
246
  void *used_chunk_p = base + va_used_chunk;
247
- mem_chunk_descriptor_t *mcd_used_chunk = used_chunk_p;
248
- size_t uc_size = *(size_t *)used_chunk_p;
247
+ lmc_mem_descriptor_t *md = base;
248
+ lmc_mem_chunk_descriptor_t *mcd_used_chunk = used_chunk_p;
249
249
  size_t va_c_free_chunk = 0;
250
- mem_chunk_descriptor_t* c_free_chunk = base + va_c_free_chunk;
250
+ lmc_mem_chunk_descriptor_t* c_free_chunk = base + va_c_free_chunk;
251
251
  size_t va_previous = 0;
252
252
  size_t va_c_free_end = 0;
253
- if (!(chunk >= sizeof(mem_descriptor_t) + sizeof(size_t)) ||
254
- !is_va_valid(base, chunk)) {
255
- printf("lmc_free: Invalid pointer: %zd\n", chunk);
256
- return;
257
- }
258
253
  #ifdef LMC_DEBUG_ALLOC
259
254
  if (uc_size == 0) {
260
255
  printf("SIZE is 0!\n");
261
256
  lmc_dump(base);
262
257
  abort();
263
258
  }
264
- memset(base + chunk, 0xF9, uc_size - sizeof(size_t));
259
+ memset(base + va_used_chunk - sizeof(size_t), 0xF9, uc_size - sizeof(size_t));
265
260
  #endif
266
261
  int freed = 0;
267
262
  while (c_free_chunk) {
@@ -274,7 +269,9 @@ void lmc_free(void *base, size_t chunk) {
274
269
  // ----------------------
275
270
  if (va_c_free_end == va_used_chunk) {
276
271
  freed = 1;
272
+ LMC_TEST_CRASH
277
273
  c_free_chunk->size += uc_size;
274
+ LMC_TEST_CRASH
278
275
  lmc_check_coalesce(base, va_c_free_chunk);
279
276
  break;
280
277
  } else
@@ -285,7 +282,7 @@ void lmc_free(void *base, size_t chunk) {
285
282
  // ----------------------
286
283
  if (va_used_chunk + uc_size == va_c_free_chunk) {
287
284
  freed = 1;
288
- mem_chunk_descriptor_t *p = base + va_previous;
285
+ lmc_mem_chunk_descriptor_t *p = base + va_previous;
289
286
  mcd_used_chunk->next = c_free_chunk->next;
290
287
  mcd_used_chunk->size = uc_size + c_free_chunk->size;
291
288
  p->next = va_used_chunk;
@@ -318,7 +315,162 @@ void lmc_free(void *base, size_t chunk) {
318
315
  #endif
319
316
  }
320
317
 
318
+ void lmc_free(void *base, size_t chunk) {
319
+ #ifdef LMC_DEBUG_ALLOC
320
+ size_t mb = __s("free1", lmc_status(base, "lmc_free1"), 0, 0);
321
+ #endif
322
+ if (chunk == 0) { return; }
323
+ if (!(chunk >= sizeof(lmc_mem_descriptor_t) + sizeof(size_t)) ||
324
+ !lmc_is_va_valid(base, chunk)) {
325
+ printf("lmc_free: Invalid pointer: %zd\n", chunk);
326
+ return;
327
+ }
328
+ size_t va_used_chunk = chunk - sizeof(size_t);
329
+ void *used_chunk_p = base + va_used_chunk;
330
+ size_t uc_size = *(size_t *)used_chunk_p;
331
+ __lmc_free(base, va_used_chunk, uc_size);
332
+ }
333
+
321
334
  void lmc_realloc(void *base, size_t chunk) {
322
335
  // check if enough reserved space, true: resize; otherwise: alloc new and
323
336
  // then free
324
337
  }
338
+
339
+ int lmc_um_getbit(char *bf, int i) {
340
+ bf += i / 8; return (*bf & (1 << (i % 8))) != 0;
341
+ }
342
+
343
+ void lmc_um_setbit(char *bf, int i, int v) {
344
+ bf += i / 8;
345
+ if (v) *bf |= 1 << (i % 8);
346
+ else *bf &= ~(1 << (i % 8));
347
+ }
348
+
349
+ int lmc_um_find_leaks(void *base, char *bf) {
350
+ lmc_mem_descriptor_t *md = base;
351
+ size_t i;
352
+ // check if gap size if smaller than sizeof(free_chunk_t)
353
+ int gap = 0;
354
+ size_t gs = 0;
355
+ size_t m;
356
+ size_t gap_count = 0;
357
+ size_t space = 0;
358
+ memset(&m, 0xFF, sizeof(m));
359
+ for (i = 0; i < md->total_size; ++i) {
360
+ if (!gap) {
361
+ size_t *b = (void *)bf + i / 8;
362
+ while (*b == m && i < md->total_size - sizeof(size_t)) {
363
+ i += sizeof(size_t) * 8; b++;
364
+ }
365
+ }
366
+ if (lmc_um_getbit(bf, i) == 0) {
367
+ if (!gap) {
368
+ gs = i;
369
+ gap = 1;
370
+ gap_count++;
371
+ }
372
+ } else {
373
+ if (gap) {
374
+ gap = 0;
375
+ space += i - gs;
376
+ __lmc_free(base, gs, i - gs);
377
+ }
378
+ }
379
+ }
380
+ if (gap) {
381
+ gap = 0;
382
+ space += i - gs;
383
+ __lmc_free(base, gs, i - gs);
384
+ }
385
+ //printf("total leaks: %zd block, %zd bytes total\n", gap_count, space);
386
+ return 1;
387
+ }
388
+
389
+ int lmc_um_check_unmarked(void *base, char *bf, size_t va, size_t size) {
390
+ size_t i;
391
+ size_t n;
392
+ memset(&n, 0x0, sizeof(n));
393
+ size_t end = va + size;
394
+ for (i = va; i < va + size; ++i) {
395
+ size_t *b = (void *)bf + i / 8;
396
+ while (*b == n && i < end - sizeof(size_t)) {
397
+ i += sizeof(size_t) * 8; b++;
398
+ }
399
+ if (lmc_um_getbit(bf, i) != 0) {
400
+ //printf("umarked2: FAILED at: %zd\n", i);
401
+ //printf("umarked2: FAILED start: %zd\n", va);
402
+ //size_t d = i;
403
+ //while (lmc_um_getbit(bf, d) != 0) { --d; }
404
+ //printf("area starts at: %zd\n", d);
405
+ //size_t e = i;
406
+ //while (lmc_um_getbit(bf, e) != 0) { ++e; }
407
+ //printf("area ends at: %zd\n", e);
408
+ return 0;
409
+ }
410
+ }
411
+ return 1;
412
+ }
413
+
414
+ int lmc_um_mark(void *base, char *bf, size_t va, size_t size) {
415
+ size_t i;
416
+ lmc_mem_descriptor_t *md = base;
417
+ if ((va > sizeof(lmc_mem_descriptor_t)) &&
418
+ (!lmc_is_va_valid(base, va) || !lmc_is_va_valid(base, va + size))) {
419
+ printf("Error: VA start out of range: va: %zd - %zd max %zd!\n",
420
+ va, va + size, md->total_size);
421
+ return 0;
422
+ }
423
+ if (!lmc_um_check_unmarked(base, bf, va, size)) return 0;
424
+ for (i = va; i < va + size; ++i) {
425
+ if (i % 8 == 0) {
426
+ size_t b_start = i / 8;
427
+ size_t b_end = (va + size - 1) / 8;
428
+ if (b_start != b_end) {
429
+ memset(bf + b_start, 0xFF, b_end - b_start);
430
+ i += (b_end * 8) - va;
431
+ }
432
+ }
433
+ lmc_um_setbit(bf, i, 1);
434
+ }
435
+ return 1;
436
+ }
437
+
438
+ int lmc_um_mark_allocated(void *base, char *bf, size_t va) {
439
+ size_t real_va = va - sizeof(size_t);
440
+ size_t s = *(size_t *)(base + real_va);
441
+ return lmc_um_mark(base, bf, real_va, s);
442
+ }
443
+
444
+ char *lmc_um_new_mem_usage_bitmap(void *base) {
445
+ lmc_mem_descriptor_t *md = base;
446
+ size_t ts = ((md->total_size + 7) / 8);
447
+ char *bf = calloc(1, ts);
448
+ size_t va = md->first_free;
449
+ if (!lmc_um_mark(base, bf, 0, sizeof(lmc_mem_descriptor_t))) goto failed;
450
+ lmc_mem_chunk_descriptor_t *c;
451
+ while (va) {
452
+ c = base + va;
453
+ if (!lmc_um_mark(base, bf, va, c->size)) goto failed;
454
+ va = c->next;
455
+ }
456
+ return bf;
457
+
458
+ failed:
459
+ free(bf);
460
+ return 0;
461
+ }
462
+
463
+ lmc_log_descriptor_t *lmc_log_op(void *base, int opid) {
464
+ lmc_mem_descriptor_t *md = base;
465
+ lmc_log_descriptor_t *l = &md->log;
466
+ l->op_id = opid;
467
+ l->p1 = l->p2 = 0x0;
468
+ return l;
469
+ }
470
+
471
+ void lmc_log_finish(void *base) {
472
+ lmc_mem_descriptor_t *md = base;
473
+ lmc_log_descriptor_t *l = &md->log;
474
+ l->op_id = 0;
475
+ l->p1 = l->p2 = 0x0;
476
+ }