+#if SLAB_DEBUG & SLAB_DEBUG_LOG
+
+FILE *slab_log;
+
+struct slab_log_entry
+{
+ struct timeval tv;
+ void *slab;
+ ssize_t size;
+};
+
+static void
+close_slab_log(void)
+{
+ fclose(slab_log);
+}
+
+static void
+slab_log_alloc(void *slab, size_t size)
+{
+ struct slab_log_entry sle;
+
+ gettimeofday(&sle.tv, NULL);
+ sle.slab = slab;
+ sle.size = (ssize_t)size;
+
+ if (!slab_log)
+ {
+ const char *fname;
+ fname = getenv("SLAB_LOG_FILE");
+ if (!fname)
+ fname = "slab.log";
+ slab_log = fopen(fname, "w");
+ atexit(close_slab_log);
+ }
+
+ fwrite(&sle, sizeof(sle), 1, slab_log);
+}
+
+static void
+slab_log_free(void *slab, size_t size)
+{
+ struct slab_log_entry sle;
+
+ gettimeofday(&sle.tv, NULL);
+ sle.slab = slab;
+ sle.size = -(ssize_t)size;
+ fwrite(&sle, sizeof(sle), 1, slab_log);
+}
+
+static void
+slab_log_unmap(void *slab)
+{
+ struct slab_log_entry sle;
+
+ gettimeofday(&sle.tv, NULL);
+ sle.slab = slab;
+ sle.size = 0;
+ fwrite(&sle, sizeof(sle), 1, slab_log);
+}
+
+#else
+# define slab_log_alloc(SLAB, SIZE)
+# define slab_log_free(SLAB, SIZE)
+# define slab_log_unmap(SLAB)
+#endif
+
+#if (SLAB_DEBUG & SLAB_DEBUG_PERMS) && defined(HAVE_MPROTECT)
+
+static void
+slab_protect(struct slab *slab)
+{
+ mprotect(slab, (char*)(slab + 1) - (char*)slab->base, PROT_NONE);
+}
+
+static void
+slab_unprotect(struct slab *slab)
+{
+ mprotect(slab, (char*)(slab + 1) - (char*)slab->base, PROT_READ | PROT_WRITE);
+}
+
+#else
+# define slab_protect(SLAB) (void)(SLAB)
+# define slab_unprotect(SLAB) (void)(SLAB)
+#endif
+