x86: Rename VPD (XCC)
[akaros.git] / kern / include / slab.h
index 79787e9..28e89a7 100644 (file)
@@ -8,7 +8,7 @@
  *
  * There is a list of kmem_cache, which are the caches of objects of a given
  * size.  This list is sorted in order of size.  Each kmem_cache has three
- * lists of slabs: full, partial, and empty.  
+ * lists of slabs: full, partial, and empty.
  *
  * For large objects, the kmem_slabs point to bufctls, which have the address
  * of their large buffers.  These slabs can consist of more than one contiguous
  * address of the next free item.  The slab structure is stored at the end of
  * the page.  There is only one page per slab.
  *
- * TODO: Note, that this is a minor pain in the ass, and worth thinking about
- * before implementing.  To keep the constructor's state valid, we can't just
- * overwrite things, so we need to add an extra 4-8 bytes per object for the
- * pointer, and then pass over that data when we return the actual object's
- * address.  This also might fuck with alignment.
+ * Be careful with source arenas and NOTOUCH.  If a cache's source arena is not
+ * page-aligned memory, you need to set NOTOUCH.  Otherwise, for small objects,
+ * a slab will be constructed that uses the source for a page of objects.
  */
 
-#ifndef ROS_KERN_SLAB_H
-#define ROS_KERN_SLAB_H
+#pragma once
 
 #include <ros/common.h>
 #include <arch/mmu.h>
 #include <sys/queue.h>
 #include <atomic.h>
+#include <hash_helper.h>
+#include <arena.h>
 
 /* Back in the day, their cutoff for "large objects" was 512B, based on
  * measurements and on not wanting more than 1/8 of internal fragmentation. */
 #define NUM_BUF_PER_SLAB 8
 #define SLAB_LARGE_CUTOFF (PGSIZE / NUM_BUF_PER_SLAB)
 
+#define KMC_NAME_SZ                            32
+#define KMC_MAG_MIN_SZ                 8
+#define KMC_MAG_MAX_SZ                 62              /* chosen for mag size and caching */
+
+/* Cache creation flags: */
+#define KMC_NOTOUCH                            0x0001  /* Can't use source/object's memory */
+#define KMC_QCACHE                             0x0002  /* Cache is an arena's qcache */
+#define __KMC_USE_BUFCTL               0x1000  /* Internal use */
+
+struct kmem_magazine {
+       SLIST_ENTRY(kmem_magazine)      link;
+       unsigned int                            nr_rounds;
+       void                                            *rounds[KMC_MAG_MAX_SZ];
+} __attribute__((aligned(ARCH_CL_SIZE)));
+SLIST_HEAD(kmem_mag_slist, kmem_magazine);
+
+struct kmem_pcpu_cache {
+       int8_t                                          irq_state;
+       unsigned int                            magsize;
+       struct kmem_magazine            *loaded;
+       struct kmem_magazine            *prev;
+       size_t                                          nr_allocs_ever;
+} __attribute__((aligned(ARCH_CL_SIZE)));
+
+struct kmem_depot {
+       spinlock_t                                      lock;
+       struct kmem_mag_slist           not_empty;
+       struct kmem_mag_slist           empty;
+       unsigned int                            magsize;
+       unsigned int                            nr_empty;
+       unsigned int                            nr_not_empty;
+       unsigned int                            busy_count;
+       uint64_t                                        busy_start;
+};
+
 struct kmem_slab;
 
 /* Control block for buffers for large-object slabs */
 struct kmem_bufctl {
-       TAILQ_ENTRY(kmem_bufctl) link;
+       BSD_LIST_ENTRY(kmem_bufctl) link;
        void *buf_addr;
        struct kmem_slab *my_slab;
 };
-TAILQ_HEAD(kmem_bufctl_list, kmem_bufctl);
+BSD_LIST_HEAD(kmem_bufctl_list, kmem_bufctl);
 
 /* Slabs contain the objects.  Can be either full, partial, or empty,
  * determined by checking the number of objects busy vs total.  For large
@@ -55,7 +89,6 @@ TAILQ_HEAD(kmem_bufctl_list, kmem_bufctl);
  * is used instead.*/
 struct kmem_slab {
        TAILQ_ENTRY(kmem_slab) link;
-       size_t obj_size;
        size_t num_busy_obj;
        size_t num_total_obj;
        union {
@@ -67,38 +100,50 @@ TAILQ_HEAD(kmem_slab_list, kmem_slab);
 
 /* Actual cache */
 struct kmem_cache {
-       SLIST_ENTRY(kmem_cache) link;
+       TAILQ_ENTRY(kmem_cache) all_kmc_link;
+       struct kmem_pcpu_cache *pcpu_caches;
+       struct kmem_depot depot;
        spinlock_t cache_lock;
-       const char *name;
        size_t obj_size;
+       size_t import_amt;
        int align;
        int flags;
+       struct arena *source;
        struct kmem_slab_list full_slab_list;
        struct kmem_slab_list partial_slab_list;
        struct kmem_slab_list empty_slab_list;
-       void (*ctor)(void *, size_t);
-       void (*dtor)(void *, size_t);
+       int (*ctor)(void *obj, void *priv, int flags);
+       void (*dtor)(void *obj, void *priv);
+       void *priv;
+       unsigned long nr_cur_alloc;
+       unsigned long nr_direct_allocs_ever;
+       struct hash_helper hh;
+       struct kmem_bufctl_list *alloc_hash;
+       struct kmem_bufctl_list static_hash[HASH_INIT_SZ];
+       char name[KMC_NAME_SZ];
+       TAILQ_ENTRY(kmem_cache) import_link;
 };
 
-/* List of all kmem_caches, sorted in order of size */
-SLIST_HEAD(kmem_cache_list, kmem_cache);
-extern struct kmem_cache_list kmem_caches;
+extern struct kmem_cache_tailq all_kmem_caches;
 
 /* Cache management */
 struct kmem_cache *kmem_cache_create(const char *name, size_t obj_size,
                                      int align, int flags,
-                                     void (*ctor)(void *, size_t),
-                                     void (*dtor)(void *, size_t));
+                                     struct arena *source,
+                                     int (*ctor)(void *, void *, int),
+                                     void (*dtor)(void *, void *),
+                                     void *priv);
 void kmem_cache_destroy(struct kmem_cache *cp);
 /* Front end: clients of caches use these */
 void *kmem_cache_alloc(struct kmem_cache *cp, int flags);
 void kmem_cache_free(struct kmem_cache *cp, void *buf);
 /* Back end: internal functions */
 void kmem_cache_init(void);
-void kmem_cache_grow(struct kmem_cache *cp);
 void kmem_cache_reap(struct kmem_cache *cp);
-
-/* Debug */
-void print_kmem_cache(struct kmem_cache *kc);
-void print_kmem_slab(struct kmem_slab *slab);
-#endif // !ROS_KERN_SLAB_H
+unsigned int kmc_nr_pcpu_caches(void);
+/* Low-level interface for initializing a cache. */
+void __kmem_cache_create(struct kmem_cache *kc, const char *name,
+                         size_t obj_size, int align, int flags,
+                         struct arena *source,
+                         int (*ctor)(void *, void *, int),
+                         void (*dtor)(void *, void *), void *priv);