/*
- * Copyright (c) 2006-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
/* Allocate extra in case we need to manually align the pointer */
#define MCACHE_ALLOC_SIZE \
- (sizeof (void *) + MCACHE_SIZE(ncpu) + CPU_CACHE_SIZE)
+ (sizeof (void *) + MCACHE_SIZE(ncpu) + CPU_CACHE_LINE_SIZE)
#define MCACHE_CPU(c) \
(mcache_cpu_t *)((void *)((char *)(c) + MCACHE_SIZE(cpu_number())))
#define MCACHE_LOCK_TRY(l) lck_mtx_try_lock(l)
static int ncpu;
+static unsigned int cache_line_size;
static lck_mtx_t *mcache_llock;
static struct thread *mcache_llock_owner;
static lck_attr_t *mcache_llock_attr;
char name[32];
ncpu = ml_get_max_cpus();
+ (void) mcache_cache_line_size(); /* prime it */
mcache_llock_grp_attr = lck_grp_attr_alloc_init();
mcache_llock_grp = lck_grp_alloc_init("mcache.list",
mcache_reap_interval = 15 * hz;
mcache_applyall(mcache_cache_bkt_enable);
mcache_ready = 1;
+
+ printf("mcache: %d CPU(s), %d bytes CPU cache line size\n",
+ ncpu, CPU_CACHE_LINE_SIZE);
}
/*
return (mcache_flags);
}
+/*
+ * Return the CPU cache line size.
+ */
+__private_extern__ unsigned int
+mcache_cache_line_size(void)
+{
+ if (cache_line_size == 0) {
+ ml_cpu_info_t cpu_info;
+ ml_cpu_get_info(&cpu_info);
+ cache_line_size = cpu_info.cache_line_size;
+ }
+ return (cache_line_size);
+}
+
/*
* Create a cache using the zone allocator as the backend slab allocator.
* The caller may specify any alignment for the object; if it specifies 0
* is okay since we've allocated extra space for this.
*/
cp = (mcache_t *)
- P2ROUNDUP((intptr_t)buf + sizeof (void *), CPU_CACHE_SIZE);
+ P2ROUNDUP((intptr_t)buf + sizeof (void *), CPU_CACHE_LINE_SIZE);
pbuf = (void **)((intptr_t)cp - sizeof (void *));
*pbuf = buf;
for (c = 0; c < ncpu; c++) {
mcache_cpu_t *ccp = &cp->mc_cpu[c];
- VERIFY(IS_P2ALIGNED(ccp, CPU_CACHE_SIZE));
+ VERIFY(IS_P2ALIGNED(ccp, CPU_CACHE_LINE_SIZE));
lck_mtx_init(&ccp->cc_lock, cp->mc_cpu_lock_grp,
cp->mc_cpu_lock_attr);
ccp->cc_objs = -1;
}
__private_extern__ void
-mcache_buffer_log(mcache_audit_t *mca, void *addr, mcache_t *cp)
+mcache_buffer_log(mcache_audit_t *mca, void *addr, mcache_t *cp,
+ struct timeval *base_ts)
{
+ struct timeval now, base = { 0, 0 };
+ void *stack[MCACHE_STACK_DEPTH + 1];
+
mca->mca_addr = addr;
mca->mca_cache = cp;
mca->mca_pthread = mca->mca_thread;
mca->mca_thread = current_thread();
bcopy(mca->mca_stack, mca->mca_pstack, sizeof (mca->mca_pstack));
mca->mca_pdepth = mca->mca_depth;
- bzero(mca->mca_stack, sizeof (mca->mca_stack));
- mca->mca_depth = OSBacktrace(mca->mca_stack, MCACHE_STACK_DEPTH);
+ bzero(stack, sizeof (stack));
+ mca->mca_depth = OSBacktrace(stack, MCACHE_STACK_DEPTH + 1) - 1;
+ bcopy(&stack[1], mca->mca_stack, sizeof (mca->mca_pstack));
+
+ mca->mca_ptstamp = mca->mca_tstamp;
+ microuptime(&now);
+ if (base_ts != NULL)
+ base = *base_ts;
+ /* tstamp is in ms relative to base_ts */
+ mca->mca_tstamp = ((now.tv_usec - base.tv_usec) / 1000);
+ if ((now.tv_sec - base.tv_sec) > 0)
+ mca->mca_tstamp += ((now.tv_sec - base.tv_sec) * 1000);
}
__private_extern__ void