]> Zhao Yanbai Git Server - minix.git/commitdiff
. removed const from putenv() for g++
authorBen Gras <ben@minix3.org>
Tue, 20 Jun 2006 08:45:04 +0000 (08:45 +0000)
committerBen Gras <ben@minix3.org>
Tue, 20 Jun 2006 08:45:04 +0000 (08:45 +0000)
. added safecopies.c:
  these are library functions to maintain grant tables in own address space
. sys_safecopy.c:
  interfaces to kernel calls to perform safe copy functions in from or to
  foreign process
. changes in i/o fields (type merged with request) reflected in
  library functions (sys_out.c, sys_vinb.c, sys_vinl.c, sys_vinw.c,
  sys_voutb.c, sys_voutl.c, sys_voutw.c)
. type merged with request in sys_sdevio, also now accepts offset which
  is used when a grant is specified (the _DIO_SAFE subtype)
. system printf() function changed to send DIAGNOSTICS_S messages, which
  specify a grant id instead of a direct address for the buffer to be
  printed; tty and log can then safecopy the buffer

14 files changed:
lib/other/putenv.c
lib/syslib/Makefile.in
lib/syslib/safecopies.c [new file with mode: 0644]
lib/syslib/sys_in.c
lib/syslib/sys_out.c
lib/syslib/sys_safecopy.c [new file with mode: 0644]
lib/syslib/sys_sdevio.c
lib/syslib/sys_vinb.c
lib/syslib/sys_vinl.c
lib/syslib/sys_vinw.c
lib/syslib/sys_voutb.c
lib/syslib/sys_voutl.c
lib/syslib/sys_voutw.c
lib/sysutil/kputc.c

index d49ab9d0a21524d5be1d02e915f6c1357ac07e2f..455ad5c5b0e5b6f50cdb2c0a1e302af1bc940bf7 100755 (executable)
@@ -14,7 +14,7 @@ extern _CONST char ***_penviron;
 
 int
 putenv(name)
-_CONST char *name;
+char *name;
 {
        register _CONST char **v = *_penviron;
        register char *r;
index 11215b9996867267aa8761806926a2b298e6d419..2a4b8b0255b449b4ffabf6eee8e8a7ab2f9b127f 100644 (file)
@@ -23,6 +23,7 @@ libsys_FILES=" \
        pci_rescan_bus.c \
        pci_reserve.c \
        pci_slot_name.c \
+       safecopies.c \
        sys_abort.c \
        sys_endsig.c \
        sys_eniop.c \
@@ -40,6 +41,7 @@ libsys_FILES=" \
        sys_nice.c \
        sys_out.c \
        sys_physcopy.c \
+       sys_safecopy.c \
        sys_sdevio.c \
        sys_segctl.c \
        sys_setalarm.c \
diff --git a/lib/syslib/safecopies.c b/lib/syslib/safecopies.c
new file mode 100644 (file)
index 0000000..01dff96
--- /dev/null
@@ -0,0 +1,264 @@
+
+/* Library functions to maintain internal data copying tables.
+ *
+ * April 21 2006: Initial version (Ben Gras)
+ *
+ */
+
+#include <lib.h>
+#include <errno.h>
+#include <minix/sysutil.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+PRIVATE cp_grant_t *grants = NULL;
+PRIVATE int ngrants = 0, dynamic = 1;
+
+PUBLIC int
+cpf_preallocate(cp_grant_t *new_grants, int new_ngrants)
+{
+/* Use a statically allocated block of grants as our grant table.
+ * This means we can't grow it dynamically any more.
+ *
+ * This function is used in processes that can't safely call realloc().
+ */
+       int s;
+
+       /* If any table is already in place, we can't change it. */
+       if(ngrants > 0) {
+               errno = EBUSY;
+               return -1;
+       }
+
+       /* Update kernel about the table. */
+       if((s=sys_privctl(SELF, SYS_PRIV_SET_GRANTS,
+               new_ngrants, new_grants))) {
+               return -1;
+       }
+
+       /* Update internal data. dynamic = 0 means no realloc()ing will be done
+        * and we can't grow beyond this size.
+        */
+       grants = new_grants;
+       ngrants = new_ngrants;
+       dynamic = 0;
+
+       return 0;
+}
+
+PRIVATE void
+cpf_grow(void)
+{
+/* Grow the grants table if possible. If a preallocated block has been
+ * submitted ('dynamic' is clear), we can't grow it. Otherwise, realloc().
+ * Caller is expected to check 'ngrants' to see if the call was successful.
+ */
+       cp_grant_t *new_grants;
+       cp_grant_id_t g;
+       int new_size;
+
+       /* Can't grow if static block already assigned. */
+       if(!dynamic)
+               return;
+
+       new_size = (1+ngrants)*2;
+       assert(new_size > ngrants);
+
+       /* Grow block to new size. */
+       if(!(new_grants=realloc(grants, new_size * sizeof(grants[0]))))
+               return;
+
+       /* Make sure new slots are marked unused (CPF_USED is clear). */
+       for(g = ngrants; g < new_size; g++)
+               grants[g].cp_flags = 0;
+
+       /* Inform kernel about new size (and possibly new location). */
+       if(sys_privctl(SELF, SYS_PRIV_SET_GRANTS, new_size, new_grants))
+               return; /* Failed - don't grow then. */
+
+       /* Update internal data. */
+       grants = new_grants;
+       ngrants = new_size;
+}
+
+PRIVATE cp_grant_id_t
+cpf_new_grantslot(void)
+{
+/* Find a new, free grant slot in the grant table, grow it if
+ * necessary. If no free slot is found and the grow failed,
+ * return -1. Otherwise, return grant slot number.
+ */
+       static cp_grant_id_t i = 0;
+       cp_grant_id_t g;
+       int n = 0;
+
+       /* Any slots at all? */
+       if(ngrants < 1) {
+               errno = ENOSPC;
+               return -1;
+       }
+
+       /* Find free slot. */
+       for(g = i % ngrants;
+           n < ngrants && (grants[g].cp_flags & CPF_USED); n++)
+               g = (g+1) % ngrants;
+
+       /* Where to start searching next time. */
+       i = g+1;
+
+       assert(g <= ngrants);
+       assert(n <= ngrants);
+
+       /* No free slot found? */
+       if(n == ngrants) {
+               cpf_grow();
+               assert(n <= ngrants); /* ngrants can't shrink. */
+               if(n == ngrants) {
+                       /* ngrants hasn't increased. */
+                       errno = ENOSPC;
+                       return -1;
+               }
+               /* The new grant is the first available new grant slot. */
+               g = n;
+       }
+
+       /* Basic sanity checks - if we get this far, g must be a valid,
+        * free slot.
+        */
+       assert(GRANT_VALID(g));
+       assert(g >= 0);
+       assert(g < ngrants);
+       assert(!(grants[g].cp_flags & CPF_USED));
+
+       return g;
+}
+
+PUBLIC cp_grant_id_t
+cpf_grant_direct(endpoint_t who_to, vir_bytes addr, size_t bytes, int access)
+{
+       cp_grant_id_t g;
+       /* Get new slot to put new grant in. */
+       if((g = cpf_new_grantslot()) < 0)
+               return -1;
+
+       /* Don't let caller specify any other flags than access. */
+       if(access & ~(CPF_READ|CPF_WRITE)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       assert(GRANT_VALID(g));
+       assert(g >= 0);
+       assert(g < ngrants);
+       assert(!(grants[g].cp_flags & CPF_USED));
+
+       grants[g].cp_flags = CPF_USED | CPF_DIRECT | access;
+       grants[g].cp_u.cp_direct.cp_who_to = who_to;
+       grants[g].cp_u.cp_direct.cp_start = addr;
+       grants[g].cp_u.cp_direct.cp_len = bytes;
+
+       return g;
+}
+
+PUBLIC cp_grant_id_t
+cpf_grant_indirect(endpoint_t who_to, endpoint_t who_from, cp_grant_id_t gr)
+{
+/* Grant process A access into process B. B has granted us access as grant
+ * id 'gr'.
+ */
+       cp_grant_id_t g;
+
+       /* Obtain new slot. */
+       if((g = cpf_new_grantslot()) < 0)
+               return -1;
+
+       /* Basic sanity checks. */
+       assert(GRANT_VALID(g));
+       assert(g >= 0);
+       assert(g < ngrants);
+       assert(!(grants[g].cp_flags & CPF_USED));
+
+       /* Fill in new slot data. */
+       grants[g].cp_flags = CPF_USED | CPF_INDIRECT;
+       grants[g].cp_u.cp_indirect.cp_who_to = who_to;
+       grants[g].cp_u.cp_indirect.cp_who_from = who_from;
+       grants[g].cp_u.cp_indirect.cp_grant = gr;
+
+       return g;
+}
+
+PUBLIC cp_grant_id_t
+cpf_grant_magic(endpoint_t who_to, endpoint_t who_from,
+       vir_bytes addr, size_t bytes, int access)
+{
+/* Grant process A access into process B. Not everyone can do this. */
+       cp_grant_id_t g;
+
+       /* Obtain new slot. */
+       if((g = cpf_new_grantslot()) < 0)
+               return -1;
+
+       /* Basic sanity checks. */
+       assert(GRANT_VALID(g));
+       assert(g >= 0);
+       assert(g < ngrants);
+       assert(!(grants[g].cp_flags & CPF_USED));
+
+       /* Don't let caller specify any other flags than access. */
+       if(access & ~(CPF_READ|CPF_WRITE)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* Fill in new slot data. */
+       grants[g].cp_flags = CPF_USED | CPF_MAGIC | access;
+       grants[g].cp_u.cp_magic.cp_who_to = who_to;
+       grants[g].cp_u.cp_magic.cp_who_from = who_from;
+       grants[g].cp_u.cp_magic.cp_start = addr;
+       grants[g].cp_u.cp_magic.cp_len = bytes;
+
+       return g;
+}
+
+PUBLIC int
+cpf_revoke(cp_grant_id_t g)
+{
+/* Revoke previously granted access, identified by grant id. */
+       /* First check slot validity, and if it's in use currently. */
+       if(g < 0 || g >= ngrants || !(grants[g].cp_flags & CPF_USED)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* Make grant invalid by setting flags to 0, clearing CPF_USED.
+        * This invalidates the grant.
+        */
+       grants[g].cp_flags = 0;
+
+       return 0;
+}
+
+PUBLIC int
+cpf_lookup(cp_grant_id_t g, endpoint_t *granter, endpoint_t *grantee)
+{
+       /* First check slot validity, and if it's in use currently. */
+       if(!GRANT_VALID(g) ||
+          g < 0 || g >= ngrants || !(grants[g].cp_flags & CPF_USED)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if(grants[g].cp_flags & CPF_DIRECT) {
+               if(granter) *granter = SELF;
+               if(grantee) *grantee = grants[g].cp_u.cp_direct.cp_who_to;
+       } else if(grants[g].cp_flags & CPF_MAGIC) {
+               if(granter) *granter = grants[g].cp_u.cp_magic.cp_who_from;
+               if(grantee) *grantee = grants[g].cp_u.cp_magic.cp_who_to;
+       } else  return -1;
+
+       return 0;
+}
+
index cfa203ad7f6903e39baf6f2bd31c35a964efae8f..2a6fa0cc812606a50b9b7cfe19fb791a264c47e0 100644 (file)
@@ -11,8 +11,7 @@ int type;                             /* byte, word, long */
     message m_io;
     int result;
 
-    m_io.DIO_TYPE = type;
-    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_REQUEST = _DIO_INPUT | type;
     m_io.DIO_PORT = port;
 
     result = _taskcall(SYSTASK, SYS_DEVIO, &m_io);
index 0d62d5ffc81515518c88e3e0158155432b64a483..f1f2a03d7110a1a0327b129383b496e3499e1e06 100644 (file)
@@ -10,8 +10,7 @@ int type;                             /* byte, word, long */
 {
     message m_io;
 
-    m_io.DIO_TYPE = type;
-    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_REQUEST = _DIO_OUTPUT | type;
     m_io.DIO_PORT = port;
     m_io.DIO_VALUE = value;
 
diff --git a/lib/syslib/sys_safecopy.c b/lib/syslib/sys_safecopy.c
new file mode 100644 (file)
index 0000000..2060c3f
--- /dev/null
@@ -0,0 +1,48 @@
+
+#include "syslib.h"
+
+#include <minix/safecopies.h>
+
+PUBLIC int sys_safecopyfrom(endpoint_t src_e,
+       cp_grant_id_t gr_id, vir_bytes offset,
+       vir_bytes address, size_t bytes,
+       int my_seg)
+{
+/* Transfer a block of data for which the other process has previously
+ * given permission. 
+ */
+
+  message copy_mess;
+
+  copy_mess.SCP_FROM_TO = src_e;
+  copy_mess.SCP_INFO = SCP_MAKEINFO(my_seg);
+  copy_mess.SCP_GID = gr_id;
+  copy_mess.SCP_OFFSET = (long) offset;
+  copy_mess.SCP_ADDRESS = (char *) address;
+  copy_mess.SCP_BYTES = (long) bytes;
+
+  return(_taskcall(SYSTASK, SYS_SAFECOPYFROM, &copy_mess));
+
+}
+
+PUBLIC int sys_safecopyto(endpoint_t dst_e,
+       cp_grant_id_t gr_id, vir_bytes offset,
+       vir_bytes address, size_t bytes,
+       int my_seg)
+{
+/* Transfer a block of data for which the other process has previously
+ * given permission. 
+ */
+
+  message copy_mess;
+
+  copy_mess.SCP_FROM_TO = dst_e;
+  copy_mess.SCP_INFO = SCP_MAKEINFO(my_seg);
+  copy_mess.SCP_GID = gr_id;
+  copy_mess.SCP_OFFSET = (long) offset;
+  copy_mess.SCP_ADDRESS = (char *) address;
+  copy_mess.SCP_BYTES = (long) bytes;
+
+  return(_taskcall(SYSTASK, SYS_SAFECOPYTO, &copy_mess));
+
+}
index 481d74ae6ffc060e49a4963f9053d210c567dce5..e6bfcb2f83952b3eb418e1bd341ace1a2295dc00 100644 (file)
@@ -3,23 +3,23 @@
 /*===========================================================================*
  *                                sys_sdevio                                *
  *===========================================================================*/
-PUBLIC int sys_sdevio(req, port, type, proc_nr, buffer, count)
-int req;                               /* request: DIO_INPUT/ DIO_OUTPUT */
+PUBLIC int sys_sdevio(req, port, proc_nr, buffer, count, offset)
+int req;                               /* request: DIO_{IN,OUT}PUT_* */
 long port;                             /* port address to read from */
-int type;                              /* byte, word, long */
-int proc_nr;                           /* process where buffer is */
+endpoint_t proc_nr;                    /* process where buffer is */
 void *buffer;                          /* pointer to buffer */
 int count;                             /* number of elements */
+vir_bytes offset;                      /* offset from grant */
 {
     message m_io;
     int result;
 
     m_io.DIO_REQUEST = req;
-    m_io.DIO_TYPE = type;
     m_io.DIO_PORT = port;
     m_io.DIO_VEC_ENDPT = proc_nr;
     m_io.DIO_VEC_ADDR = buffer;
     m_io.DIO_VEC_SIZE = count;
+    m_io.DIO_OFFSET = offset;
 
     return(_taskcall(SYSTASK, SYS_SDEVIO, &m_io));
 }
index c74d79970d6b8433c03e6ac0942aa6706c419ba5..af1cc2be7c761e59552bb39cd52b3b80b3b532bf 100644 (file)
@@ -9,8 +9,7 @@ int nr_ports;                           /* nr of pairs to be processed */
 {
     message m_io;
 
-    m_io.DIO_TYPE = DIO_BYTE;
-    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_REQUEST = _DIO_INPUT | _DIO_BYTE;
     m_io.DIO_VEC_ADDR = (char *) pvb_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index 8ff83c34c742e0fd5271ff1b6ce3c6c21b016237..1649a76e30552fd11993ff492264c95e005fa95e 100644 (file)
@@ -9,8 +9,7 @@ int nr_ports;                           /* nr of pairs to be processed */
 {
     message m_io;
 
-    m_io.DIO_TYPE = DIO_LONG;
-    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_REQUEST = _DIO_INPUT | _DIO_LONG;
     m_io.DIO_VEC_ADDR = (char *) pvl_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index e01c46610d8d7d30883e14f841d1a7089a93d7ec..c2ba3eeb7a73d10feffc1ca01485640e97bbedde 100644 (file)
@@ -10,8 +10,7 @@ int nr_ports;                         /* nr of pairs to be processed */
 {
     message m_io;
 
-    m_io.DIO_TYPE = DIO_WORD;
-    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_REQUEST = _DIO_WORD | _DIO_INPUT;
     m_io.DIO_VEC_ADDR = (char *) pvw_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index 35d379bd92cbedc067a9879e7e9aa1f6decdc410..42467274e7845f8a378d50821f6c9d4a0bf7036f 100644 (file)
@@ -8,8 +8,7 @@ pvb_pair_t *pvb_pairs;                  /* (port,byte-value)-pairs */
 int nr_ports;                          /* nr of pairs to be processed */
 {
     message m_io;
-    m_io.DIO_TYPE = DIO_BYTE;
-    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_REQUEST = _DIO_OUTPUT | _DIO_BYTE;
     m_io.DIO_VEC_ADDR = (char *) pvb_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index 184223dae73e337bcb0519cf59feb6762ca66384..1cec294d99d751127fa43d0d435c32816da1ae6d 100644 (file)
@@ -9,8 +9,7 @@ int nr_ports;                           /* nr of pairs to be processed */
 {
     message m_io;
 
-    m_io.DIO_TYPE = DIO_LONG;
-    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_REQUEST = _DIO_OUTPUT | _DIO_LONG;
     m_io.DIO_VEC_ADDR = (char *) pvl_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index a8d20f70e7ee0495abf6f47512bceec5dc8f8eb6..107e2ecde9385ee85ec2b84d6d3588d71cf85caf 100644 (file)
@@ -10,8 +10,7 @@ int nr_ports;                         /* nr of pairs to be processed */
 {
     message m_io;
 
-    m_io.DIO_TYPE = DIO_WORD;
-    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_REQUEST = _DIO_OUTPUT | _DIO_WORD;
     m_io.DIO_VEC_ADDR = (char *) pvw_pairs;
     m_io.DIO_VEC_SIZE = nr_ports;
     return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
index 18aa3d03ac3d7cb0661dadce4636eba0e007f9d5..ba1f23fe91b47da4b2e47f086964c299f5af8de7 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "sysutil.h"
 
+static char print_buf[80];     /* output is buffered here */
+
 /*===========================================================================*
  *                             kputc                                        *
  *===========================================================================*/
@@ -17,21 +19,42 @@ int c;
 {
 /* Accumulate another character.  If 0 or buffer full, print it. */
   static int buf_count;                /* # characters in the buffer */
-  static char print_buf[80];   /* output is buffered here */
   message m;
 
   if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
+#define PRINTPROCS (sizeof(procs)/sizeof(procs[0]))
        int procs[] = OUTPUT_PROCS_ARRAY;
+       static int firstprint = 1;
+       static cp_grant_t printgrant_buffer[PRINTPROCS];
+       static cp_grant_id_t printgrants[PRINTPROCS];
        int p;
 
+       if(firstprint) {
+               /* First time? Initialize grant table;
+                * Grant printing processes read copy access to our
+                * print buffer. (So buffer can't be on stack!)
+                */
+               cpf_preallocate(printgrant_buffer, PRINTPROCS);
+               for(p = 0; procs[p] != NONE; p++) {
+                       printgrants[p] = cpf_grant_direct(procs[p], print_buf,
+                               sizeof(print_buf), CPF_READ);
+               }
+               firstprint = 0;
+       }
+
        for(p = 0; procs[p] != NONE; p++) {
                /* Send the buffer to this output driver. */
                m.DIAG_BUF_COUNT = buf_count;
-               m.DIAG_PRINT_BUF = print_buf;
-               m.DIAG_ENDPT = SELF;
-               m.m_type = DIAGNOSTICS;
+               if(GRANT_VALID(printgrants[p])) {
+                       m.m_type = DIAGNOSTICS_S;
+                       m.DIAG_PRINT_BUF_G = printgrants[p];
+               } else {
+                       m.m_type = DIAGNOSTICS;
+                       m.DIAG_PRINT_BUF_G = print_buf;
+               }
                (void) _sendrec(procs[p], &m);
        }
+
        buf_count = 0;
 
        /* If the output fails, e.g., due to an ELOCKED, do not retry output