localmemcache 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }