libsys: allow for grant preallocation

Since the grant table is allocated dynamically, a system service always
runs the risk of running out of memory at run time when trying to
allocate a grant.  In order to allow services to mitigate that risk,
grants can now be preallocated, typically at system service startup,
using the new cpf_prealloc(3) libsys function.  The function takes a
'count' parameter that indicates the number of additional grants to
preallocate.  Thus, the function may be called from multiple submodules
within a service, each preallocating their own maximum of grants that
it may need at run time.

Change-Id: I6904726a722a8c27dfe2efa470e683718f310272
This commit is contained in:
David van Moolenbroek 2016-11-04 17:31:40 +00:00
parent 5d5fbe79c1
commit 5edbea5063
2 changed files with 26 additions and 10 deletions

View File

@ -78,9 +78,13 @@ struct vscp_vec {
#define GRANT_FAULTED 1 /* CPF_TRY: a soft fault occurred */
/* Prototypes for functions in libsys. */
cp_grant_id_t cpf_grant_direct(endpoint_t, vir_bytes, size_t, int);
cp_grant_id_t cpf_grant_indirect(endpoint_t, endpoint_t, cp_grant_id_t);
cp_grant_id_t cpf_grant_magic(endpoint_t, endpoint_t, vir_bytes, size_t, int);
void cpf_prealloc(unsigned int count);
cp_grant_id_t cpf_grant_direct(endpoint_t who_to, vir_bytes addr, size_t bytes,
int access);
cp_grant_id_t cpf_grant_indirect(endpoint_t who_to, endpoint_t who_from,
cp_grant_id_t gr);
cp_grant_id_t cpf_grant_magic(endpoint_t who_to, endpoint_t who_from,
vir_bytes addr, size_t bytes, int access);
int cpf_revoke(cp_grant_id_t grant_id);
/* START OF DEPRECATED API */

View File

@ -44,23 +44,35 @@ static cp_grant_t *grants = NULL;
static int ngrants = 0;
static int freelist = -1;
static void
cpf_grow(void)
/*
* Preallocate more grants that will be free for subsequent use. If a specific
* number of grants is given (i.e., count > 0), the total number of grants will
* be increased by that amount. If no number of grants is given (count == 0),
* double(ish) the size of the table. The latter is used internally. This
* function may fail, either because the maximum number of slots is reached or
* because no new memory can be allocated. In that case, nothing will change;
* the caller must check afterward whether there are newly available grants.
*/
void
cpf_prealloc(unsigned int count)
{
/* Grow the grants table if possible. */
cp_grant_t *new_grants;
int g, new_size;
if(!ngrants) {
if (!ngrants && count <= NR_STATIC_GRANTS) {
/* Use statically allocated grants the first time. */
new_size = NR_STATIC_GRANTS;
new_grants = static_grants;
}
else {
/* Double(ish) the size, up to the maximum number of slots. */
if (ngrants >= GRANT_MAX_IDX)
return;
new_size = (1+ngrants)*2;
if (count != 0) {
if (count > (unsigned)(GRANT_MAX_IDX - ngrants))
count = (unsigned)(GRANT_MAX_IDX - ngrants);
new_size = ngrants + (int)count;
} else
new_size = (1+ngrants)*2;
if (new_size >= GRANT_MAX_IDX)
new_size = GRANT_MAX_IDX;
assert(new_size > ngrants);
@ -116,7 +128,7 @@ cpf_new_grantslot(void)
/* Obtain a free slot. */
if ((g = freelist) == -1) {
/* Table full - try to make the table larger. */
cpf_grow();
cpf_prealloc(0);
if ((g = freelist) == -1) {
/* ngrants hasn't increased. */
errno = ENOSPC;