[git] GnuPG - branch, npth-2, updated. gnupg-2.1.0beta3-12-g122d1d1

by Marcus Brinkmann cvs at cvs.gnupg.org
Tue Jan 24 18:48:44 CET 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, npth-2 has been updated
       via  122d1d1babf919d491390ad2e3fa8ab8271a19a1 (commit)
      from  baa383a8d5db9b1458a2994fb0f7523d7a6849b2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 122d1d1babf919d491390ad2e3fa8ab8271a19a1
Author: Marcus Brinkmann <marcus.brinkmann at ruhr-uni-bochum.de>
Date:   Tue Jan 24 17:37:01 2012 +0100

    Port LDAP wrapper to NPTH.
    
    * agent/gpg-agent.c (handle_connections): Handle error.
    * dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c: Port to NPTH.

diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 12d92d0..9bd0c46 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1865,7 +1865,9 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 #endif
 
   ret = npth_attr_init(&tattr);
-  /* FIXME: Check error.  */
+  if (ret)
+    log_fatal ("error allocating thread attributes: %s\n",
+	       gpg_strerror (ret));
   npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
 
 #ifndef HAVE_W32_SYSTEM
diff --git a/dirmngr/dirmngr_ldap.c b/dirmngr/dirmngr_ldap.c
index 166ba4a..f166f19 100644
--- a/dirmngr/dirmngr_ldap.c
+++ b/dirmngr/dirmngr_ldap.c
@@ -58,13 +58,13 @@
 #include "i18n.h"
 #include "util.h"
 
-/* With the ldap wrapper, there is no need for the pth_enter and leave
+/* With the ldap wrapper, there is no need for the npth_unprotect and leave
    functions; thus we redefine them to nops.  If we are not using the
    ldap wrapper process we need to include the prototype for our
    module's main function.  */
 #ifdef USE_LDAPWRAPPER
-static void pth_enter (void) { }
-static void pth_leave (void) { }
+static void npth_unprotect (void) { }
+static void npth_protect (void) { }
 #else
 # include "./ldap-wrapper.h"
 #endif
@@ -392,9 +392,9 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
   LDAPMessage *item;
   int any = 0;
 
-  for (pth_enter (), item = ldap_first_entry (ld, msg), pth_leave ();
+  for (npth_unprotect (), item = ldap_first_entry (ld, msg), npth_protect ();
        item;
-       pth_enter (), item = ldap_next_entry (ld, item), pth_leave ())
+       npth_unprotect (), item = ldap_next_entry (ld, item), npth_protect ())
     {
       BerElement *berctx;
       char *attr;
@@ -414,11 +414,11 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
         }
 
 
-      for (pth_enter (), attr = my_ldap_first_attribute (ld, item, &berctx),
-             pth_leave ();
+      for (npth_unprotect (), attr = my_ldap_first_attribute (ld, item, &berctx),
+             npth_protect ();
            attr;
-           pth_enter (), attr = my_ldap_next_attribute (ld, item, berctx),
-             pth_leave ())
+           npth_unprotect (), attr = my_ldap_next_attribute (ld, item, berctx),
+             npth_protect ())
         {
           struct berval **values;
           int idx;
@@ -455,9 +455,9 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
                 }
             }
 
-          pth_enter ();
+          npth_unprotect ();
           values = my_ldap_get_values_len (ld, item, attr);
-          pth_leave ();
+          npth_protect ();
 
           if (!values)
             {
@@ -618,19 +618,19 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
 
 
   set_timeout (myopt);
-  pth_enter ();
+  npth_unprotect ();
   ld = my_ldap_init (host, port);
-  pth_leave ();
+  npth_protect ();
   if (!ld)
     {
       log_error (_("LDAP init to `%s:%d' failed: %s\n"),
                  host, port, strerror (errno));
       return -1;
     }
-  pth_enter ();
+  npth_unprotect ();
   /* Fixme:  Can we use MYOPT->user or is it shared with other theeads?.  */
   ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
-  pth_leave ();
+  npth_protect ();
   if (ret)
     {
       log_error (_("binding to `%s:%d' failed: %s\n"),
@@ -640,13 +640,13 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
     }
 
   set_timeout (myopt);
-  pth_enter ();
+  npth_unprotect ();
   rc = my_ldap_search_st (ld, dn, ludp->lud_scope, filter,
                           myopt->multi && !myopt->attr && ludp->lud_attrs?
                           ludp->lud_attrs:attrs,
                           0,
                           &myopt->timeout, &msg);
-  pth_leave ();
+  npth_protect ();
   if (rc == LDAP_SIZELIMIT_EXCEEDED && myopt->multi)
     {
       if (es_fwrite ("E\0\0\0\x09truncated", 14, 1, myopt->outstream) != 1)
diff --git a/dirmngr/ldap-wrapper-ce.c b/dirmngr/ldap-wrapper-ce.c
index 9bc5d06..9af70af 100644
--- a/dirmngr/ldap-wrapper-ce.c
+++ b/dirmngr/ldap-wrapper-ce.c
@@ -106,12 +106,93 @@ struct outstream_cookie_s
 {
   int refcount; /* Reference counter - possible values are 1 and 2.  */
 
+  /* We don't need a mutex for the conditions, as npth provides a
+     simpler condition interface that relies on the global lock.  This
+     can be used if we never yield between testing the condition and
+     waiting on it.  */
+  npth_cond_t wait_data; /* Condition that data is available.  */
+  npth_cond_t wait_space; /* Condition that space is available.  */
+
   int eof_seen;       /* EOF indicator.  */
-  size_t buffer_len;  /* The valid length of the BUFFER.  */
+  char buffer[4000];  /* Data ring buffer.  */
+  size_t buffer_len;  /* The amount of data in the BUFFER.  */
   size_t buffer_pos;  /* The next read position of the BUFFER.  */
-  char buffer[4000];  /* Data buffer.  */
 };
 
+#define BUFFER_EMPTY(c) ((c)->buffer_len == 0)
+#define BUFFER_FULL(c) ((c)->buffer_len == DIM((c)->buffer))
+#define BUFFER_DATA_AVAILABLE(c) ((c)->buffer_len)
+#define BUFFER_SPACE_AVAILABLE(c) (DIM((c)->buffer) - (c)->buffer_len)
+#define BUFFER_INC_POS(c,n) (c)->buffer_pos = ((c)->buffer_pos + (n)) % DIM((c)->buffer)
+#define BUFFER_CUR_POS(c) (&(c)->buffer[(c)->buffer_pos])
+
+static int
+buffer_get_data (struct outstream_cookie_s *cookie, char *dst, int cnt)
+{
+  int amount;
+  int left;
+  int chunk;
+
+  amount = cnt;
+  if (BUFFER_DATA_AVAILABLE (cookie) < amount)
+    amount = BUFFER_DATA_AVAILABLE (cookie);
+  left = amount;
+
+  /* How large is the part up to the end of the buffer array?  */
+  chunk = DIM(cookie->buffer) - cookie->buffer_pos;
+  if (chunk > left)
+    chunk = left;
+
+  memcpy (dst, BUFFER_CUR_POS (cookie), chunk);
+  BUFFER_INC_POS (cookie, chunk);
+  left -= chunk;
+  dst += chunk;
+
+  if (left)
+    {
+      memcpy (dst, BUFFER_CUR_POS (cookie), left);
+      BUFFER_INC_POS (cookie, left);
+    }
+
+  return amount;
+}
+
+
+static int
+buffer_put_data (struct outstream_cookie_s *cookie, const char *src, int cnt)
+{
+  int amount;
+  int remain;
+  int left;
+  int chunk;
+
+  remain = DIM(cookie->buffer) - cookie->buffer_len;
+
+  amount = cnt;
+  if (remain < amount)
+    amount = remain;
+  left = amount;
+
+  /* How large is the part up to the end of the buffer array?  */
+  chunk = DIM(cookie->buffer) - cookie->buffer_pos;
+  if (chunk > left)
+    chunk = left;
+
+  memcpy (BUFFER_CUR_POS (cookie), src, chunk);
+  BUFFER_INC_POS (cookie, chunk);
+  left -= chunk;
+  src += chunk;
+
+  if (left)
+    {
+      memcpy (BUFFER_CUR_POS (cookie), src, left);
+      BUFFER_INC_POS (cookie, left);
+    }
+
+  cookie->buffer_len -= amount;
+  return amount;
+}
+
 
 /* The writer function for the outstream.  This is used to transfer
    the output of the ldap wrapper thread to the ksba reader object.  */
@@ -120,43 +201,42 @@ outstream_cookie_writer (void *cookie_arg, const void *buffer, size_t size)
 {
   struct outstream_cookie_s *cookie = cookie_arg;
   const char *src;
-  char *dst;
   ssize_t nwritten = 0;
+  int res;
+  ssize_t amount = 0;
 
   src = buffer;
   do
     {
+      int was_empty = 0;
+
       /* Wait for free space.  */
-      while (cookie->buffer_len == DIM (cookie->buffer))
+      while (BUFFER_FULL(cookie))
         {
           /* Buffer is full:  Wait for space.  */
-          pth_yield (NULL);
+          res = npth_cond_wait (&cookie->wait_space, NULL);
+	  if (res)
+	    {
+	      gpg_err_set_errno (res);
+	      return -1;
+	    }
         }
 
+      if (BUFFER_EMPTY(cookie))
+	was_empty = 1;
+
       /* Copy data.  */
-      dst = cookie->buffer + cookie->buffer_len;
-      while (size && cookie->buffer_len < DIM (cookie->buffer))
-        {
-          *dst++ = *src++;
-          size--;
-          cookie->buffer_len++;
-          nwritten++;
-        }
-    }
-  while (size);  /* Until done.  */
+      nwritten = buffer_put_data (cookie, buffer, size);
+      size -= nwritten;
+      src += nwritten;
+      amount += nwritten;
 
-  if (nwritten)
-    {
-      /* Signal data is available - a pth_yield is sufficient because
-         the test is explicit.  To increase performance we could do a
-         pth_yield to the other thread and only fall back to yielding
-         to any thread if that returns an error (i.e. the other thread
-         is not runnable).  However our w32pth does not yet support
-         yielding to a specific thread, thus this won't help. */
-      pth_yield (NULL);
+      if (was_empty)
+	npth_cond_signal (&cookie->wait_data);
     }
+  while (size);  /* Until done.  */
 
-  return nwritten;
+  return amount;
 }
 
 
@@ -165,7 +245,11 @@ outstream_release_cookie (struct outstream_cookie_s *cookie)
 {
   cookie->refcount--;
   if (!cookie->refcount)
-    xfree (cookie);
+    {
+      npth_cond_destroy (&cookie->wait_data);
+      npth_cond_destroy (&cookie->wait_space);
+      xfree (cookie);
+    }
 }
 
 
@@ -198,6 +282,7 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
   char *dst;
   const char *src;
   size_t nread = 0;
+  int was_full = 0;
 
   if (!buffer && !count && !r_nread)
     return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported.  */
@@ -205,31 +290,26 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
   *r_nread = 0;
   dst = buffer;
 
-  while (cookie->buffer_pos == cookie->buffer_len)
+  while (BUFFER_EMPTY(cookie))
     {
       if (cookie->eof_seen)
         return gpg_error (GPG_ERR_EOF);
 
       /* Wait for data to become available.  */
-      pth_yield (NULL);
+      npth_cond_wait (&cookie->wait_data, NULL);
     }
 
+  if (BUFFER_FULL(cookie))
+    was_full = 1;
+
   src = cookie->buffer + cookie->buffer_pos;
-  while (count && cookie->buffer_pos < cookie->buffer_len)
+  nread = buffer_get_data (cookie, buffer, count);
+
+  if (was_full)
     {
-      *dst++ = *src++;
-      count--;
-      cookie->buffer_pos++;
-      nread++;
+      npth_cond_signal (&cookie->wait_space);
     }
 
-  if (cookie->buffer_pos == cookie->buffer_len)
-    cookie->buffer_pos = cookie->buffer_len = 0;
-
-  /* Now there should be some space available.  We do this even if
-     COUNT was zero so to give the writer end a chance to continue.  */
-  pth_yield (NULL);
-
   *r_nread = nread;
   return 0; /* Success.  */
 }
@@ -351,10 +431,12 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
 {
   gpg_error_t err;
   struct ldap_wrapper_thread_parms *parms;
-  pth_attr_t tattr;
+  npth_attr_t tattr;
   es_cookie_io_functions_t outstream_func = { NULL };
   struct outstream_cookie_s *outstream_cookie;
   ksba_reader_t reader;
+  int res;
+  npth_t thread;
 
   (void)ctrl;
 
@@ -381,6 +463,22 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
     }
   outstream_cookie->refcount++;
 
+  res = npth_cond_init (&outstream_cookie->wait_data, NULL);
+  if (res)
+    {
+      free_arg_list (parms->arg_list);
+      xfree (parms);
+      return gpg_error_from_errno (res);
+    }
+  res = npth_cond_init (&outstream_cookie->wait_space, NULL);
+  if (res)
+    {
+      npth_cond_destroy (&outstream_cookie->wait_data);
+      free_arg_list (parms->arg_list);
+      xfree (parms);
+      return gpg_error_from_errno (res);
+    }
+
   err = ksba_reader_new (&reader);
   if (!err)
     err = ksba_reader_set_release_notify (reader,
@@ -407,27 +505,37 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
   if (!parms->outstream)
     {
       err = gpg_error_from_syserror ();
-      free_arg_list (parms->arg_list);
+      ksba_reader_release (reader);
       outstream_release_cookie (outstream_cookie);
+      free_arg_list (parms->arg_list);
       xfree (parms);
       return err;
     }
   outstream_cookie->refcount++;
 
-  tattr = pth_attr_new();
-  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
-  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024);
-  pth_attr_set (tattr, PTH_ATTR_NAME, "ldap-wrapper");
+  res = npth_attr_init(&tattr);
+  if (res)
+    {
+      err = gpg_error_from_errno (res);
+      ksba_reader_release (reader);
+      free_arg_list (parms->arg_list);
+      es_fclose (parms->outstream);
+      xfree (parms);
+      return err;
+    }
+  npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
 
-  if (pth_spawn (tattr, ldap_wrapper_thread, parms))
-    parms = NULL; /* Now owned by the thread.  */
-  else
+  res = npth_create (&thread, &tattr, ldap_wrapper_thread, parms);
+  npth_attr_destroy (&tattr);
+  if (res)
     {
-      err = gpg_error_from_syserror ();
+      err = gpg_error_from_errno (res);
       log_error ("error spawning ldap wrapper thread: %s\n",
-                 strerror (errno) );
+                 strerror (res) );
     }
-  pth_attr_destroy (tattr);
+  else
+    parms = NULL; /* Now owned by the thread.  */
+
   if (parms)
     {
       free_arg_list (parms->arg_list);

-----------------------------------------------------------------------

Summary of changes:
 agent/gpg-agent.c         |    4 +-
 dirmngr/dirmngr_ldap.c    |   34 ++++----
 dirmngr/ldap-wrapper-ce.c |  212 ++++++++++++++++++++++++++++++++++-----------
 3 files changed, 180 insertions(+), 70 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list