Skip to content

Commit

Permalink
libsys: allow for grant preallocation
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dcvmoole committed Apr 30, 2017
1 parent 5d5fbe7 commit 5edbea5
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
10 changes: 7 additions & 3 deletions minix/include/minix/safecopies.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
26 changes: 19 additions & 7 deletions minix/lib/libsys/safecopies.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5edbea5

Please sign in to comment.