]> Zhao Yanbai Git Server - minix.git/commitdiff
libsys: allow for grant preallocation 79/3479/2
authorDavid van Moolenbroek <david@minix3.org>
Fri, 4 Nov 2016 17:31:40 +0000 (17:31 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Sun, 30 Apr 2017 13:15:57 +0000 (13:15 +0000)
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
minix/lib/libsys/safecopies.c

index c1214a285c264a0202fb21ac735d68cadd2b9098..4d74e95ae333049ccb6af345eecd96f0d141c993 100644 (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 */
index e22620ff1b0e58d2890a414427f8b345123bb72d..607a67e9dcdbc06f9069c029ce3e5eb7a7ea72f1 100644 (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;