13
edits
m (reserve_cur() --> reserve_current()) |
(Revise based on bug #427109 comments #19 and #26) |
||
Line 27: | Line 27: | ||
== Memory reserve API == | == Memory reserve API == | ||
The allocator | <pre>/* | ||
* The allocator maintains a memory reserve that is used to satisfy allocation | |||
* requests when no additional memory can be acquired from the operating | |||
* system. Under normal operating conditions, the reserve size is at least | |||
* reserve_min bytes. If the reserve is depleted or insufficient to satisfy an | |||
* allocation request, then condition notifications are sent to one or more of | |||
* the registered callback functions: | |||
* | |||
* RESERVE_CND_LOW: The reserve had to be used to satisfy an allocation | |||
* request, which dropped the reserve size below the | |||
* minimum. The callee should try to free memory in order | |||
* to restore the reserve. | |||
* | |||
* RESERVE_CND_CRIT: The reserve was not large enough to satisfy a pending | |||
* allocation request. The callee must free adequate memory | |||
* in order to prevent application failure. | |||
* | |||
* RESERVE_CND_FAIL: An allocation request could not be satisfied, despite all | |||
* attempts. The allocator is about to terminate the | |||
* application. | |||
* | |||
* The order in which the callback functions are called is only loosely | |||
* specified: in the absence of interposing callback | |||
* registrations/unregistrations or condition notification mask modifications, | |||
* enabled callbacks will be called in an arbitrary round-robin order. | |||
* | |||
* Condition notifications are sent to callbacks only while conditions exist. | |||
* For example, just before the allocator sends a RESERVE_CND_LOW condition | |||
* notification to a callback, the reserve is in fact depleted. However, due | |||
* to allocator concurrency, the reserve may have been restored by the time the | |||
* callback function executes. Furthermore, if the reserve is restored at some | |||
* point during the delivery of condition notifications to callbacks, no | |||
* further deliveries will occur, since the condition no longer exists. | |||
* | |||
* Callback functions can freely call back into the allocator (i.e. the | |||
* allocator releases all internal resources before calling each callback | |||
* function), though use of the x*() functions is discouraged, since recursive | |||
* callbacks are likely to result (which places extra burden on the application | |||
* to avoid deadlocking). | |||
*/ | |||
/* Memory reserve condition types. */ | |||
typedef enum { | |||
RESERVE_CND_NONE = 0x0, /* No condition. */ | |||
RESERVE_CND_LOW = 0x1, | |||
RESERVE_CND_CRIT = 0x2, | |||
RESERVE_CND_FAIL = 0x4, | |||
RESERVE_CND_ALL = 0x7 /* Union of all conditions. */ | |||
} reserve_cnd_t; | |||
/* | |||
* Reserve condition notification callback function type definition. | |||
* | |||
* Inputs: | |||
* ctx: Opaque application data, as passed to reserve_cb_register(). | |||
* cnd: Condition type being delivered. | |||
* size: Allocation request size for the allocation that caused the condition. | |||
* | |||
* Output: | |||
* ret: If false, block further callbacks to the callee for the condition type | |||
* currently being delivered. | |||
*/ | |||
typedef bool reserve_cb_t(void *ctx, reserve_cnd_t cnd, size_t size); | |||
/* | |||
* Register a callback function. | |||
* | |||
* Inputs: | |||
* cb: Callback function pointer. | |||
* ctx: Opaque application data, passed to cb(). | |||
* mask: Mask of condition types to deliver to the callback function. To | |||
* receive callbacks for a condition type, include it in the mask. | |||
*/ | |||
void reserve_cb_register(reserve_cb_t *cb, void *ctx, reserve_cnd_t mask); | |||
/* Unregister a callback function. */ | |||
void reserve_cb_unregister(reserve_cb_t *cb); | |||
/* | |||
* Get the mask of condition types that are currently enabled for a callback | |||
* function. | |||
* | |||
* Input: | |||
* cb: Callback function pointer. | |||
* | |||
* Output: | |||
* ret: Mask of condition types that may be delivered to cb. | |||
*/ | |||
reserve_cnd_t reserve_cb_getmask(reserve_cb_t *cb); | |||
/* | |||
* Set the mask of conditions that may be delivered to a callback. | |||
* | |||
* Inputs: | |||
* cb: Callback function pointer. | |||
* mask: Mask of condition types to deliver to the callback function. To | |||
* receive callbacks for a condition type, include it in the mask. | |||
* | |||
* Output: | |||
* ret: Previous mask of condition types that were to be delivered to the | |||
* callback function. | |||
*/ | |||
reserve_cnd_t reserve_cb_setmask(reserve_cb_t *cb, reserve_cnd_t mask); | |||
/* | |||
* Enable delivery of condition types that are included in mask. | |||
* | |||
* Inputs: | |||
* cb: Callback function pointer. | |||
* mask: Mask of condition types to merge into the current set of enabled | |||
* condition types. | |||
* | |||
* Output: | |||
* ret: Previous mask of condition types that were to be delivered to the | |||
* callback function. | |||
*/ | |||
reserve_cnd_t reserve_cb_enable(reserve_cb_t *cb, reserve_cnd_t mask); | |||
/* | |||
* Disable delivery of condition types that are included in mask. | |||
* | |||
* Inputs: | |||
* cb: Callback function pointer. | |||
* mask: Mask of condition types to remove from current set of enabled | |||
* condition types. | |||
* | |||
* Output: | |||
* ret: Previous mask of condition types that were to be delivered to the | |||
* callback function. | |||
*/ | |||
reserve_cnd_t reserve_cb_disable(reserve_cb_t *cb, reserve_cnd_t mask); | |||
/* | |||
* Get the current reserve size. | |||
* | |||
* ret: Current reserve size. | |||
*/ | |||
size_t reserve_cur_get(void); | |||
/* | |||
* Get the minimum acceptable reserve size. If the reserve drops below this | |||
* value, the RESERVE_CND_LOW condition notification is sent to the callbacks. | |||
* | |||
* ret: Minimum acceptable reserve size. | |||
*/ | |||
size_t reserve_min_get(void); | |||
/* | |||
* Set the minimum acceptable reserve size. | |||
* | |||
* min: Reserve threshold. | |||
* ret: False if the reserve was successfully resized; true otherwise. Note | |||
* that failure to resize the reserve also results in a RESERVE_CND_LOW | |||
* condition. | |||
*/ | |||
bool reserve_min_set(size_t min); | |||
</pre> | |||
== Implementation (non-)details == | == Implementation (non-)details == |
edits