From 8541f20ee7cb98f930d6b66e64b30a024610b87a Mon Sep 17 00:00:00 2001
From: root <root>
Date: Sun, 11 May 2008 19:11:05 +0000
Subject: implement high-level eio functions (untested), bugfixes

---
 config.h.in |   3 -
 eio.c       | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
 eio.h       |  30 +++++----
 3 files changed, 201 insertions(+), 50 deletions(-)

diff --git a/config.h.in b/config.h.in
index 210b22a..1dedbb4 100644
--- a/config.h.in
+++ b/config.h.in
@@ -71,6 +71,3 @@
 
 /* Version number of package */
 #undef VERSION
-
-/* _GNU_SOURCE required for readahead (linux) */
-#undef _GNU_SOURCE
diff --git a/eio.c b/eio.c
index c572738..8ac7d8a 100644
--- a/eio.c
+++ b/eio.c
@@ -273,8 +273,8 @@ static int grp_dec (eio_req *grp)
 
 void eio_destroy (eio_req *req)
 {
-  if ((req)->flags & EIO_FLAG_PTR2_FREE)
-    free (req->ptr2);
+  if ((req)->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1);
+  if ((req)->flags & EIO_FLAG_PTR2_FREE) free (req->ptr2);
 
   EIO_DESTROY (req);
 }
@@ -314,7 +314,9 @@ void eio_grp_cancel (eio_req *grp)
 
 void eio_cancel (eio_req *req)
 {
+  X_LOCK   (wrklock);
   req->flags |= EIO_FLAG_CANCELLED;
+  X_UNLOCK (wrklock);
 
   eio_grp_cancel (req);
 }
@@ -767,6 +769,18 @@ static void scandir_ (eio_req *req, worker *self)
 
 /*****************************************************************************/
 
+#define ALLOC(len)				\
+  X_LOCK (wrklock);				\
+  req->flags |= EIO_FLAG_PTR2_FREE;		\
+  X_UNLOCK (wrklock);				\
+  req->ptr2 = malloc (len);			\
+  if (!req->ptr2)				\
+    {						\
+      errno       = ENOMEM;			\
+      req->result = -1;				\
+      break;					\
+    }
+
 X_THREAD_PROC (eio_proc)
 {
   eio_req *req;
@@ -830,9 +844,12 @@ X_THREAD_PROC (eio_proc)
             case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
             case EIO_SENDFILE:  req->result = sendfile_ (req->int1, req->int2, req->offs, req->size, self); break;
 
-            case EIO_STAT:      req->result = stat      (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
-            case EIO_LSTAT:     req->result = lstat     (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
-            case EIO_FSTAT:     req->result = fstat     (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
+            case EIO_STAT:      ALLOC (sizeof (EIO_STRUCT_STAT));
+                                req->result = stat      (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
+            case EIO_LSTAT:     ALLOC (sizeof (EIO_STRUCT_STAT));
+                                req->result = lstat     (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
+            case EIO_FSTAT:     ALLOC (sizeof (EIO_STRUCT_STAT));
+                                req->result = fstat     (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
 
             case EIO_CHOWN:     req->result = chown     (req->ptr1, req->int2, req->int3); break;
             case EIO_FCHOWN:    req->result = fchown    (req->int1, req->int2, req->int3); break;
@@ -851,7 +868,8 @@ X_THREAD_PROC (eio_proc)
             case EIO_LINK:      req->result = link      (req->ptr1, req->ptr2); break;
             case EIO_SYMLINK:   req->result = symlink   (req->ptr1, req->ptr2); break;
             case EIO_MKNOD:     req->result = mknod     (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
-            case EIO_READLINK:  req->result = readlink  (req->ptr1, req->ptr2, NAME_MAX); break;
+            case EIO_READLINK:  ALLOC (NAME_MAX);
+                                req->result = readlink  (req->ptr1, req->ptr2, NAME_MAX); break;
 
             case EIO_SYNC:      req->result = 0; sync (); break;
             case EIO_FSYNC:     req->result = fsync     (req->int1); break;
@@ -1010,36 +1028,168 @@ int eio_init (void (*want_poll)(void), void (*done_poll)(void))
   X_THREAD_ATFORK (eio_atfork_prepare, eio_atfork_parent, eio_atfork_child);
 }
 
+static void eio_api_destroy (eio_req *req)
+{
+  free (req);
+}
+
+#define REQ(rtype)                                            	\
+  eio_req *req;                                                 \
+                                                                \
+  req = (eio_req *)calloc (1, sizeof *req);                     \
+  if (!req)                                                     \
+    return 0;                                                   \
+                                                                \
+  req->type = EIO_ ## rtype;                                    \
+  req->pri = EIO_DEFAULT_PRI + EIO_PRI_BIAS;                    \
+  req->finish = cb;						\
+  req->destroy = eio_api_destroy;
+
+#define SEND eio_submit (req); return req
+
+#define PATH (void)0
+
+eio_req *eio_fsync (int fd, eio_cb cb)
+{
+  REQ (FSYNC); req->int1 = fd; SEND;
+}
+
+eio_req *eio_fdatasync (int fd, eio_cb cb)
+{
+  REQ (FDATASYNC); req->int1 = fd; SEND;
+}
+
+eio_req *eio_readahead (int fd, off_t offset, size_t length, eio_cb cb)
+{
+  REQ (READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;
+}
+
+eio_req *eio_read (int fd, off_t offset, size_t length, void *data, eio_cb cb)
+{
+  REQ (READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND;
+}
+
+eio_req *eio_write (int fd, off_t offset, size_t length, void *data, eio_cb cb)
+{
+  REQ (WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND;
+}
+
+eio_req *eio_fstat (int fd, eio_cb cb)
+{
+  REQ (FSTAT); req->int1 = fd; SEND;
+}
+
+eio_req *eio_futime (int fd, double atime, double mtime, eio_cb cb)
+{
+  REQ (FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND;
+}
+
+eio_req *eio_ftruncate (int fd, off_t offset, eio_cb cb)
+{
+  REQ (FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;
+}
+
+eio_req *eio_fchmod (int fd, mode_t mode, eio_cb cb)
+{
+  REQ (FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
+}
+
+eio_req *eio_fchown (int fd, uid_t uid, gid_t gid, eio_cb cb)
+{
+  REQ (FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
+}
+
+eio_req *eio_dup2 (int fd, int fd2, eio_cb cb)
+{
+  REQ (DUP2); req->int1 = fd; req->int2 = fd2; SEND;
+}
+
+eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, eio_cb cb)
+{
+  REQ (SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND;
+}
+
+eio_req *eio_open (const char *path, int flags, mode_t mode, eio_cb cb)
+{
+  REQ (OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND;
+}
+
+eio_req *eio_readlink (const char *path, eio_cb cb)
+{
+  REQ (READLINK); PATH; SEND;
+}
+
+eio_req *eio_stat (const char *path, eio_cb cb)
+{
+  REQ (STAT); PATH; SEND;
+}
+
+eio_req *eio_lstat (const char *path, eio_cb cb)
+{
+  REQ (LSTAT); PATH; SEND;
+}
+
+eio_req *eio_utime (const char *path, double atime, double mtime, eio_cb cb)
+{
+  REQ (UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;
+}
+
+eio_req *eio_truncate (const char *path, off_t offset, eio_cb cb)
+{
+  REQ (TRUNCATE); PATH; req->offs = offset; SEND;
+}
+
+eio_req *eio_chown (const char *path, uid_t uid, gid_t gid, eio_cb cb)
+{
+  REQ (CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
+}
+
+eio_req *eio_chmod (const char *path, mode_t mode, eio_cb cb)
+{
+  REQ (CHMOD); PATH; req->int2 = (long)mode; SEND;
+}
+
+eio_req *eio_mkdir (const char *path, mode_t mode, eio_cb cb)
+{
+  REQ (MKDIR); PATH; req->int2 = (long)mode; SEND;
+}
+
+eio_req *eio_unlink (const char *path, eio_cb cb)
+{
+  REQ (UNLINK); PATH; SEND;
+}
+
+eio_req *eio_rmdir (const char *path, eio_cb cb)
+{
+  REQ (RMDIR); PATH; SEND;
+}
+
+eio_req *eio_readdir (const char *path, eio_cb cb)
+{
+  REQ (READDIR); PATH; SEND;
+}
+
+eio_req *eio_mknod (const char *path, mode_t mode, dev_t dev, eio_cb cb)
+{
+  REQ (MKNOD); PATH; req->int2 = (long)mode; req->int2 = (long)dev; SEND;
+}
+
+eio_req *eio_busy (double delay, eio_cb cb)
+{
+  REQ (BUSY); req->nv1 = delay; SEND;
+}
+
+eio_req *eio_nop (eio_cb cb)
+{
+  REQ (NOP); SEND;
+}
+
+#undef REQ
+#undef PATH
+#undef SEND
+
 #if 0
 
-eio_req *eio_fsync     (int fd, eio_cb cb);
-eio_req *eio_fdatasync (int fd, eio_cb cb);
-eio_req *eio_dupclose  (int fd, eio_cb cb);
-eio_req *eio_readahead (int fd, off_t offset, size_t length, eio_cb cb);
-eio_req *eio_read      (int fd, off_t offs, size_t length, char *data, eio_cb cb);
-eio_req *eio_write     (int fd, off_t offs, size_t length, char *data, eio_cb cb);
-eio_req *eio_fstat     (int fd, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
-eio_req *eio_futime    (int fd, double atime, double mtime, eio_cb cb);
-eio_req *eio_ftruncate (int fd, off_t offset, eio_cb cb);
-eio_req *eio_fchmod    (int fd, mode_t mode, eio_cb cb);
-eio_req *eio_fchown    (int fd, uid_t uid, gid_t gid, eio_cb cb);
-eio_req *eio_dup2      (int fd, int fd2, eio_cb cb);
-eio_req *eio_sendfile  (int out_fd, int in_fd, off_t in_offset, size_t length, eio_cb cb);
-eio_req *eio_open      (const char *path, int flags, mode_t mode, eio_cb cb);
-eio_req *eio_readlink  (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */
-eio_req *eio_stat      (const char *path, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
-eio_req *eio_lstat     (const char *path, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
-eio_req *eio_utime     (const char *path, double atime, double mtime, eio_cb cb);
-eio_req *eio_truncate  (const char *path, off_t offset, eio_cb cb);
-eio_req *eio_chmod     (const char *path, mode_t mode, eio_cb cb);
-eio_req *eio_mkdir     (const char *path, mode_t mode, eio_cb cb);
-eio_req *eio_chown     (const char *path, uid_t uid, gid_t gid, eio_cb cb);
-eio_req *eio_unlink    (const char *path, eio_cb cb);
-eio_req *eio_rmdir     (const char *path, eio_cb cb);
-eio_req *eio_readdir   (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */
-eio_req *eio_mknod     (const char *path, mode_t mode, dev_t dev, eio_cb cb);
-eio_req *eio_busy      (double delay, eio_cb cb); /* ties a thread for this long, simulating busyness */
-eio_req *eio_nop       (eio_cb cb); /* does nothing except go through the whole process */
 void
 aio_open (SV8 *pathname, int flags, int mode, SV *callback=&PL_sv_undef)
 	PROTOTYPE: $$$;$
diff --git a/eio.h b/eio.h
index 552fb2c..dee389c 100644
--- a/eio.h
+++ b/eio.h
@@ -9,10 +9,7 @@ typedef struct eio_req eio_req;
 typedef int (*eio_cb)(eio_req *req);
 
 #ifndef EIO_COMMON
-# define EIO_COMMON		\
-  eio_cb finish;		\
-  void (*destroy)(eio_req *req);\
-  void *data
+# define EIO_COMMON void *data
 #endif
 
 enum {
@@ -58,6 +55,8 @@ struct eio_req
   unsigned char flags; /* private */
   unsigned char pri; /* the priority */
 
+  eio_cb finish;
+  void (*destroy)(eio_req *req);
   void (*feed)(eio_req *req);
 
   EIO_COMMON;
@@ -67,7 +66,8 @@ struct eio_req
 
 enum {
   EIO_FLAG_CANCELLED = 0x01, /* request was cancelled */
-  EIO_FLAG_PTR2_FREE = 0x02, /* need to free(ptr2) */
+  EIO_FLAG_PTR1_FREE = 0x02, /* need to free(ptr1) */
+  EIO_FLAG_PTR2_FREE = 0x04  /* need to free(ptr2) */
 };
 
 enum {
@@ -76,7 +76,7 @@ enum {
 
   EIO_DEFAULT_PRI = 0,
   EIO_PRI_BIAS    = -EIO_PRI_MIN,
-  EIO_NUM_PRI     = EIO_PRI_MAX + EIO_PRI_BIAS + 1,
+  EIO_NUM_PRI     = EIO_PRI_MAX + EIO_PRI_BIAS + 1
 };
 
 /* returns < 0 on error, errno set
@@ -112,11 +112,10 @@ unsigned int eio_nthreads (void); /* number of worker threads in use currently *
 
 eio_req *eio_fsync     (int fd, eio_cb cb);
 eio_req *eio_fdatasync (int fd, eio_cb cb);
-eio_req *eio_dupclose  (int fd, eio_cb cb);
 eio_req *eio_readahead (int fd, off_t offset, size_t length, eio_cb cb);
-eio_req *eio_read      (int fd, off_t offs, size_t length, char *data, eio_cb cb);
-eio_req *eio_write     (int fd, off_t offs, size_t length, char *data, eio_cb cb);
-eio_req *eio_fstat     (int fd, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
+eio_req *eio_read      (int fd, off_t offset, size_t length, void *data, eio_cb cb);
+eio_req *eio_write     (int fd, off_t offset, size_t length, void *data, eio_cb cb);
+eio_req *eio_fstat     (int fd, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */
 eio_req *eio_futime    (int fd, eio_tstamp atime, eio_tstamp mtime, eio_cb cb);
 eio_req *eio_ftruncate (int fd, off_t offset, eio_cb cb);
 eio_req *eio_fchmod    (int fd, mode_t mode, eio_cb cb);
@@ -125,13 +124,13 @@ eio_req *eio_dup2      (int fd, int fd2, eio_cb cb);
 eio_req *eio_sendfile  (int out_fd, int in_fd, off_t in_offset, size_t length, eio_cb cb);
 eio_req *eio_open      (const char *path, int flags, mode_t mode, eio_cb cb);
 eio_req *eio_readlink  (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */
-eio_req *eio_stat      (const char *path, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
-eio_req *eio_lstat     (const char *path, eio_cb cb); /* stat buffer=ptr2 allocates dynamically */
+eio_req *eio_stat      (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */
+eio_req *eio_lstat     (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */
 eio_req *eio_utime     (const char *path, eio_tstamp atime, eio_tstamp mtime, eio_cb cb);
 eio_req *eio_truncate  (const char *path, off_t offset, eio_cb cb);
+eio_req *eio_chown     (const char *path, uid_t uid, gid_t gid, eio_cb cb);
 eio_req *eio_chmod     (const char *path, mode_t mode, eio_cb cb);
 eio_req *eio_mkdir     (const char *path, mode_t mode, eio_cb cb);
-eio_req *eio_chown     (const char *path, uid_t uid, gid_t gid, eio_cb cb);
 eio_req *eio_unlink    (const char *path, eio_cb cb);
 eio_req *eio_rmdir     (const char *path, eio_cb cb);
 eio_req *eio_readdir   (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */
@@ -166,5 +165,10 @@ void eio_cancel (eio_req *req);
 /* destroy a request that has never been submitted */
 void eio_destroy (eio_req *req);
 
+/*****************************************************************************/
+/* convinience functions */
+
+/*ssize_t eio_sendfile (int ofd, int ifd, off_t offset, size_t count)*/
+
 #endif
 
-- 
cgit v1.2.3