diff --git a/kernel/hshtb.h b/kernel/hshtb.h index 630ae65..63baa41 100644 --- a/kernel/hshtb.h +++ b/kernel/hshtb.h @@ -4,47 +4,81 @@ #include #include #include +#include "hal/hal.h" +#include "util/util.h" -#define HSHTB_FNV32_BASE 0x811c9dc5 +#define HSHTB_FNV32_OFF 0x811c9dc5u +#define HSHTB_FNV32_PRIME 0x01000193u -static inline uint32_t hshtb_fnv32(char *s, size_t len) { - uint32_t h = HSHTB_FNV32_BASE; +static inline uint32_t hshtb_fnv32(const void *data, size_t len) { + const unsigned char *p = (const unsigned char *)data; + uint32_t h = HSHTB_FNV32_OFF; for (size_t i = 0; i < len; i++) { - h ^= s[i]; - h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); + h ^= p[i]; + h *= HSHTB_FNV32_PRIME; } - return h >> 8; + return h; } -#define HSHTB_ALLOC(tb, name, k, keyname, out) \ +enum { + HSHTB_EMPTY = 0, + HSHTB_TAKEN = 1, + HSHTB_TOMB = 2, +}; + +#define HSHTB_ALLOC(tb, keyfield, k, out) \ do { \ - size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \ - size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \ - size_t i = idx; \ + size_t __len = sizeof((tb)) / sizeof((tb)[0]); \ + uint32_t __h = hshtb_fnv32((k), strlen((k))); \ + size_t __idx = __h % __len; \ + size_t __start = __idx; \ + typeof(&(tb)[0]) __tomb = NULL; \ do { \ - if (!(tb)->name[i].taken) { \ - (out) = &((tb)->name[i]); \ - hal_memset((out), 0, sizeof(*(out))); \ - (out)->taken = true; \ - hal_memcpy((out)->keyname, k, hal_strlen(k)); \ + if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \ + typeof(&(tb)[0]) __slot = __tomb ? __tomb : &(tb)[__idx]; \ + hal_memset(__slot, 0, sizeof(*__slot)); \ + __slot->_hshtbstate = HSHTB_TAKEN; \ + hal_memcpy(__slot->keyfield, (k), MIN(sizeof(__slot->keyfield) - 1, hal_strlen((k)))); \ + (out) = __slot; \ break; \ } \ - i = (i + 1) % len; \ - } while(i != idx); \ + if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \ + (out) = &(tb)[__idx]; \ + break; \ + } \ + if ((tb)[__idx]._hshtbstate == HSHTB_TOMB && !__tomb) { \ + __tomb = &(tb)[__idx]; \ + } \ + __idx = (__idx + 1) % __len; \ + } while(__idx != __start); \ } while(0) -#define HSHTB_GET(tb, name, k, keyname, out) \ +#define HSHTB_GET(tb, keyfield, k, out) \ do { \ - size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \ - size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \ - size_t i = idx; \ + size_t __len = sizeof((tb)) / sizeof((tb)[0]); \ + uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \ + size_t __idx = __h % __len; \ + size_t __start = __idx; \ + (out) = NULL; \ do { \ - if (hal_memcmp((tb)->name[i].keyname, k, hal_strlen(k)) == 0) { \ - (out) = &((tb)->name[i]); \ + if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \ break; \ } \ - i = (i + 1) % len; \ - } while(i != idx); \ + if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \ + (out) = &(tb)[__idx]; \ + break; \ + } \ + __idx = (__idx + 1) % __len; \ + } while(__idx != __start); \ + } while(0) + +#define HSHTB_DELETE(tb, keyfield, k) \ + do { \ + typeof(&(tb)[0]) __e; \ + HSHTB_GET((tb), (keyfield), (k), __e); \ + if (__e) { \ + __e->state = HSHTB_TOMB; \ + } \ } while(0) #endif // HSHTB_H_ diff --git a/kernel/vfs/vfs.c b/kernel/vfs/vfs.c index 95b403a..54c4b08 100644 --- a/kernel/vfs/vfs.c +++ b/kernel/vfs/vfs.c @@ -54,7 +54,7 @@ int32_t vfs_stat(char *mountpoint, const char *path, IoctlStat *stat) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); - HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); + HSHTB_GET(VFS_TABLE.mountpoints, label, mountpoint, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { @@ -68,7 +68,7 @@ int32_t vfs_fetchdirent(char *mountpoint, const char *path, IoctlDirent *direntb VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); - HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); + HSHTB_GET(VFS_TABLE.mountpoints, label, mountpoint, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { @@ -82,7 +82,7 @@ int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd, bool fo VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); - HSHTB_ALLOC(&VFS_TABLE, mountpoints, mountpoint, label, mp); + HSHTB_ALLOC(VFS_TABLE.mountpoints, label, mountpoint, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { @@ -107,7 +107,7 @@ int32_t vfs_unmount(char *mountpoint) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); - HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); + HSHTB_GET(VFS_TABLE.mountpoints, label, mountpoint, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { @@ -129,7 +129,7 @@ VfsObj *vfs_open(char *mountpoint, const char *path, uint32_t flags) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); - HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); + HSHTB_GET(VFS_TABLE.mountpoints, label, mountpoint, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { @@ -168,7 +168,7 @@ void vfs_init(void) { LOG("vfs", "init\n"); for (size_t i = 0; i < LEN(VFS_TABLE.mountpoints); i++) { - if (!VFS_TABLE.mountpoints[i].taken) continue; + if (VFS_TABLE.mountpoints[i]._hshtbstate != HSHTB_TAKEN) continue; VfsMountPoint *vmp = &VFS_TABLE.mountpoints[i]; LOG("vfs", "mount point %s: %s, backing device: %s\n", vmp->label, vfs_strings[vmp->fstype], storedev_strings[vmp->backingsd->sdtype]); diff --git a/kernel/vfs/vfs.h b/kernel/vfs/vfs.h index 41823f2..0ecf271 100644 --- a/kernel/vfs/vfs.h +++ b/kernel/vfs/vfs.h @@ -42,8 +42,9 @@ typedef struct VfsObj { } VfsObj; typedef struct VfsMountPoint { - bool taken; - uint8_t label[VFS_MOUNTPOINT_LABEL_MAX]; + int _hshtbstate; + char label[VFS_MOUNTPOINT_LABEL_MAX]; + int32_t fstype; StoreDev *backingsd;