From 5edbea50631e5089314617ad4298253cfedb7793 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Fri, 4 Nov 2016 17:31:40 +0000 Subject: [PATCH] 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 --- minix/include/minix/safecopies.h | 10 +++++++--- minix/lib/libsys/safecopies.c | 26 +++++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/minix/include/minix/safecopies.h b/minix/include/minix/safecopies.h index c1214a285..4d74e95ae 100644 --- a/minix/include/minix/safecopies.h +++ b/minix/include/minix/safecopies.h @@ -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 */ diff --git a/minix/lib/libsys/safecopies.c b/minix/lib/libsys/safecopies.c index e22620ff1..607a67e9d 100644 --- a/minix/lib/libsys/safecopies.c +++ b/minix/lib/libsys/safecopies.c @@ -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; -- 2.44.0