* The call GC_allocobj(i,k) ensures that the freelist for
* kind k objects of size i points to a non-empty
* free list. It returns a pointer to the first entry on the free list.
- * In a single-threaded world, GC_allocobj may be called to allocate
- * an object of small size lb (and NORMAL kind) as follows
+ * If not using thread-local allocation, GC_allocobj may be called to
+ * allocate an object of small size lb (and NORMAL kind) as follows
* (GC_generic_malloc_inner is a wrapper over GC_allocobj which also
* fills in GC_size_map if needed):
*
* lg = GC_size_map[lb];
+ * LOCK();
* op = GC_objfreelist[lg];
* if (NULL == op) {
* op = GC_generic_malloc_inner(lb, NORMAL);
* GC_objfreelist[lg] = obj_link(op);
* GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);
* }
+ * UNLOCK();
*
* Note that this is very fast if the free list is non-empty; it should
* only involve the execution of 4 or 5 simple instructions.
return result;
}
+/* This function should be called with the allocation lock held. */
+/* At the same time, it is safe to get a value from GC_size_map not */
+/* acquiring the allocation lock provided the obtained value is used */
+/* according to the pattern given in alloc.c file (see the comment */
+/* about GC_allocobj usage and, e.g., GC_malloc_kind_global code). */
+static void fill_size_map(size_t low_limit, size_t byte_sz, size_t granule_sz)
+ GC_ATTR_NO_SANITIZE_THREAD
+{
+ for (; low_limit <= byte_sz; low_limit++)
+ GC_size_map[low_limit] = granule_sz;
+}
+
/* Fill in additional entries in GC_size_map, including the i-th one. */
/* Note that a filled in section of the array ending at n always */
/* has the length of at least n/4. */
/* We may need one extra byte; do not always */
/* fill in GC_size_map[byte_sz]. */
- for (; low_limit <= byte_sz; low_limit++)
- GC_size_map[low_limit] = granule_sz;
+ fill_size_map(low_limit, byte_sz, granule_sz);
}
/* Allocate lb bytes for an object of kind k. */