You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC

svn commit: r350181 [158/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,978 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CDEV_CURRENT_FUNCTION _comment_
+/**
+ * @file
+ * @ingroup Port
+ * @brief Shared Semaphores
+ */
+
+#undef CDEV_CURRENT_FUNCTION
+
+#include "portpriv.h"
+#include "hyport.h"
+#include "portnls.h"
+#include "ut_hyprt.h"
+#include "hysharedhelper.h"
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define CDEV_CURRENT_FUNCTION include_header
+#include "hyshsem.h"
+#undef CDEV_CURRENT_FUNCTION
+
+/*These flags are only used internally*/
+#define CREATE_ERROR -10
+#define OPEN_ERROR  -11
+#define WRITE_ERROR -12
+#define READ_ERROR -13
+#define MALLOC_ERROR -14
+
+#define HYSH_NO_DATA -21
+#define HYSH_BAD_DATA -22
+
+#define RETRY_COUNT 10
+#define SLEEP_TIME 5
+
+#define SEMAPHORE_OPENED 2
+#define SEMAPHORE_CREATED 1
+#define SUCCESS 0
+#define FAILED -1
+#define RETRY -2
+
+#define SEMMARKER 769
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+static IDATA checkMarker (hyshsem_handle * handle, int semsetsize);
+static IDATA createbaseFile (struct HyPortLibrary *portLibrary,
+                             char *filename);
+static IDATA createSemaphore (struct HyPortLibrary *portLibrary,
+                              char *baseFile, I_32 setSize,
+                              hyshsem_handle ** handle);
+static IDATA openSemaphore (struct HyPortLibrary *portLibrary, char *baseFile,
+                            I_64 timestamp, hyshsem_handle ** handle);
+static hyshsem_handle *createsemHandle (struct HyPortLibrary *portLibrary,
+                                        int semid, int nsems, char *baseFile);
+static IDATA readbaseFile (struct HyPortLibrary *portLibrary, char *filename,
+                           hyshsem_baseFileFormat ** basefileInfo);
+static I_32 setMarker (hyshsem_handle * handle, int semsetsize);
+static I_32 findError (I_32 errorCode, I_32 errorCode2);
+static IDATA writebaseFile (struct HyPortLibrary *portLibrary, char *filename,
+                            int proj_id, key_t key, int semid, int setSize);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_open
+/**
+ * Open an existing semaphore set, or create a new one if it does not exist
+ * 
+ * @param[in] portLibrary The port library.
+ * @param[out] handle A semaphore handle is allocated and initialised for use with further calls, NULL on failure.
+ * @param[in] semname Unique identifier of the semaphore.
+ * @param[in] setSize Size of the semaphore set.
+ * @param[in] permission Permission to the semaphore set.
+ *
+ * @return
+ * \arg HYPORT_ERROR_SHSEM_OPFAILED   Failure - Error opening the semaphore
+ * \arg HYPORT_INFO_SHSEM_CREATED Success - Semaphore has been created
+ * \arg HYPORT_INFO_SHSEM_OPENED  Success - Existing semaphore has been opened
+ * \arg HYPORT_INFO_SHSEM_SEMID_DIFF Success - Existing semaphore opened, but OS Semaphore key is different
+ */
+IDATA VMCALL
+hyshsem_open (struct HyPortLibrary *portLibrary,
+              struct hyshsem_handle **handle, const char *semname,
+              int setSize, int permission)
+{
+  /* TODO: needs to be longer? dynamic? */
+  char baseFile[HYSH_MAXPATH];
+  char versionStr[32];
+  struct stat statbuf;
+  I_8 retry = RETRY_COUNT;
+  I_8 exist = 0;
+  I_32 fd;
+
+  Trc_PRT_shsem_hyshsem_open_Entry (semname, setSize, permission);
+
+  if (ensureDirectory (portLibrary) == FAILED)
+    {
+      portLibrary->error_set_last_error (portLibrary, errno,
+                                         HYPORT_ERROR_SHSEM_DATA_DIRECTORY_FAILED);
+      Trc_PRT_shsem_hyshsem_open_Exit3 ();
+      return HYPORT_ERROR_SHSEM_OPFAILED;
+    }
+
+  GET_VERSION_STRING (portLibrary, versionStr);
+  portLibrary->str_printf (portLibrary, baseFile, HYSH_MAXPATH,
+                           "%s%s_semaphore_%s", HYSH_BASEDIR, versionStr,
+                           semname);
+
+  Trc_PRT_shsem_hyshsem_open_Debug1 (baseFile);
+
+  while (retry > 0)
+    {
+      I_64 timestamp = 0;
+      I_32 rc = 0;
+
+      /* check and see whether the basefile exist */
+      rc = portLibrary->file_attr (portLibrary, baseFile);
+
+      if (HyIsFile == rc)
+        {
+          /* baseFile exist, we should try and open the semaphore */
+          Trc_PRT_shsem_hyshsem_open_Event1 (baseFile);
+          rc = openSemaphore (portLibrary, baseFile, timestamp, handle);
+        }
+      else
+        {
+          /* baseFile probably not exist, we should try and create the semaphore */
+          /* For new semaphore setsize can't be 0 - failure */
+          if (setSize == 0)
+            {
+              return HYPORT_ERROR_SHSEM_OPFAILED;
+            }
+
+          Trc_PRT_shsem_hyshsem_open_Event2 (baseFile);
+          rc = createSemaphore (portLibrary, baseFile, setSize, handle);
+        }
+
+      switch (rc)
+        {
+        case RETRY:
+          Trc_PRT_shsem_hyshsem_open_Event3 (retry);
+          usleep (100);
+          retry--;
+          break;
+        case SEMAPHORE_OPENED:
+          Trc_PRT_shsem_hyshsem_open_Exit (HYPORT_INFO_SHSEM_OPENED, *handle);
+          return HYPORT_INFO_SHSEM_OPENED;
+        case HYPORT_INFO_SHSEM_SEMID_DIFF:
+          Trc_PRT_shsem_hyshsem_open_Exit (HYPORT_INFO_SHSEM_SEMID_DIFF,
+                                           *handle);
+          return HYPORT_INFO_SHSEM_SEMID_DIFF;
+        case SEMAPHORE_CREATED:
+          Trc_PRT_shsem_hyshsem_open_Exit (HYPORT_INFO_SHSEM_CREATED,
+                                           *handle);
+          return HYPORT_INFO_SHSEM_CREATED;
+        case FAILED:
+        default:
+          Trc_PRT_shsem_hyshsem_open_Exit1 ();
+          return HYPORT_ERROR_SHSEM_OPFAILED;
+        }
+    }                           /*end while */
+
+  /* we have retried too many times, return failed */
+  portLibrary->file_unlink (portLibrary, baseFile);
+  Trc_PRT_shsem_hyshsem_open_Exit2 ();
+  return HYPORT_ERROR_SHSEM_OPFAILED;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_post
+/**
+ * post operation increments the counter in the semaphore by 1 if there is no one in wait for the semaphore. 
+ * if there are other processes suspended by wait then one of them will become runnable and 
+ * the counter remains the same. 
+ * 
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Semaphore set handle.
+ * @param[in] semset The no of semaphore in the semaphore set that you want to post.
+ * @param[in] flag The semaphore operation flag:
+ * \arg HYPORT_SHSEM_MODE_DEFAULT The default operation flag, same as 0
+ * \arg HYPORT_SHSEM_MODE_UNDO The changes made to the semaphore will be undone when this process finishes.
+ *
+ * @return 0 on success, -1 on failure.
+ */
+IDATA VMCALL
+hyshsem_post (struct HyPortLibrary * portLibrary,
+              struct hyshsem_handle * handle, UDATA semset, UDATA flag)
+{
+  struct sembuf buffer;
+  IDATA rc;
+
+  Trc_PRT_shsem_hyshsem_post_Entry (handle, semset, flag);
+  if (handle == NULL)
+    {
+      Trc_PRT_shsem_hyshsem_post_Exit1 ();
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+
+  if (semset < 0 || semset >= handle->nsems)
+    {
+      Trc_PRT_shsem_hyshsem_post_Exit2 ();
+      return HYPORT_ERROR_SHSEM_SEMSET_INVALID;
+    }
+
+  buffer.sem_num = semset;
+  buffer.sem_op = 1;            /* post */
+  if (flag & HYPORT_SHSEM_MODE_UNDO)
+    {
+      buffer.sem_flg = SEM_UNDO;
+    }
+  else
+    {
+      buffer.sem_flg = 0;
+    }
+
+  rc = semop (handle->semid, &buffer, 1);
+
+  if (-1 == rc)
+    {
+      Trc_PRT_shsem_hyshsem_post_Exit3 (rc, errno);
+    }
+  else
+    {
+      Trc_PRT_shsem_hyshsem_post_Exit (rc);
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_wait
+/**
+ * Wait operation decrements the counter in the semaphore set if the counter > 0
+ * if counter == 0 then the caller will be suspended.
+ * 
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Semaphore set handle.
+ * @param[in] semset The no of semaphore in the semaphore set that you want to post.
+ * @param[in] flag The semaphore operation flag:
+ * \arg HYPORT_SHSEM_MODE_DEFAULT The default operation flag, same as 0
+ * \arg HYPORT_SHSEM_MODE_UNDO The changes made to the semaphore will be undone when this process finishes.
+ * \arg HYPORT_SHSEM_MODE_NOWAIT The caller will not be suspended if sem == 0, a -1 is returned instead.
+ * 
+ * @return 0 on success, -1 on failure.
+ */
+IDATA VMCALL
+hyshsem_wait (struct HyPortLibrary * portLibrary,
+              struct hyshsem_handle * handle, UDATA semset, UDATA flag)
+{
+  struct sembuf buffer;
+  IDATA rc;
+
+  Trc_PRT_shsem_hyshsem_wait_Entry (handle, semset, flag);
+  if (handle == NULL)
+    {
+      Trc_PRT_shsem_hyshsem_wait_Exit1 ();
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+
+  if (semset < 0 || semset >= handle->nsems)
+    {
+      Trc_PRT_shsem_hyshsem_wait_Exit2 ();
+      return HYPORT_ERROR_SHSEM_SEMSET_INVALID;
+    }
+
+  buffer.sem_num = semset;
+  buffer.sem_op = -1;           /* wait */
+
+  if (flag & HYPORT_SHSEM_MODE_UNDO)
+    {
+      buffer.sem_flg = SEM_UNDO;
+    }
+  else
+    {
+      buffer.sem_flg = 0;
+    }
+
+  if (flag & HYPORT_SHSEM_MODE_NOWAIT)
+    {
+      buffer.sem_flg = buffer.sem_flg | IPC_NOWAIT;
+    }
+
+  rc = semop (handle->semid, &buffer, 1);
+  if (-1 == rc)
+    {
+      Trc_PRT_shsem_hyshsem_wait_Exit3 (rc, errno);
+    }
+  else
+    {
+      Trc_PRT_shsem_hyshsem_wait_Exit (rc);
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_getVal
+/**
+ * reading the value of the semaphore in the set. This function
+ * uses no synchronisation prmitives
+  * 
+ * @pre caller has to deal with synchronisation issue.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Semaphore set handle.
+ * @param[in] semset The number of semaphore in the semaphore set that you want to post.
+ * 
+ * @return -1 on failure, the value of the semaphore on success
+ * 
+ * @warning: The user will need to make sure locking is done correctly when
+ * accessing semaphore values. This is because getValue simply reads the semaphore
+ * value without stopping the access to the semaphore. Therefore the value of the semaphore
+ * can change before the function returns. 
+ */
+IDATA VMCALL
+hyshsem_getVal (struct HyPortLibrary * portLibrary,
+                struct hyshsem_handle * handle, UDATA semset)
+{
+  IDATA rc;
+  Trc_PRT_shsem_hyshsem_getVal_Entry (handle, semset);
+  if (handle == NULL)
+    {
+      Trc_PRT_shsem_hyshsem_getVal_Exit1 ();
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+
+  if (semset < 0 || semset >= handle->nsems)
+    {
+      Trc_PRT_shsem_hyshsem_getVal_Exit2 ();
+      return HYPORT_ERROR_SHSEM_SEMSET_INVALID;
+    }
+
+  rc = semctl (handle->semid, semset, GETVAL);
+  if (-1 == rc)
+    {
+      Trc_PRT_shsem_hyshsem_getVal_Exit3 (rc, errno);
+    }
+  else
+    {
+      Trc_PRT_shsem_hyshsem_getVal_Exit (rc);
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_setVal
+/**
+ * 
+ * setting the value of the semaphore specified in semset. This function
+ * uses no synchronisation prmitives
+ * 
+ * @pre Caller has to deal with synchronisation issue.
+ * 
+ * @param[in] portLibrary The port Library.
+ * @param[in] handle Semaphore set handle.
+ * @param[in] semset The no of semaphore in the semaphore set that you want to post.
+ * @param[in] value The value that you want to set the semaphore to
+ * 
+ * @warning The user will need to make sure locking is done correctly when
+ * accessing semaphore values. This is because setValue simply set the semaphore
+ * value without stopping the access to the semaphore. Therefore the value of the semaphore
+ * can change before the function returns. 
+ *
+ * @return 0 on success, -1 on failure.
+ */
+IDATA VMCALL
+hyshsem_setVal (struct HyPortLibrary * portLibrary,
+                struct hyshsem_handle * handle, UDATA semset, IDATA value)
+{
+  union semun sem_union;
+  IDATA rc;
+
+  Trc_PRT_shsem_hyshsem_setVal_Entry (handle, semset, value);
+
+  if (handle == NULL)
+    {
+      Trc_PRT_shsem_hyshsem_setVal_Exit1 ();
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+  if (semset < 0 || semset >= handle->nsems)
+    {
+      Trc_PRT_shsem_hyshsem_setVal_Exit2 ();
+      return HYPORT_ERROR_SHSEM_SEMSET_INVALID;
+    }
+
+  sem_union.val = value;
+
+  rc = semctl (handle->semid, semset, SETVAL, sem_union);
+
+  if (-1 == rc)
+    {
+      Trc_PRT_shsem_hyshsem_setVal_Exit3 (rc, errno);
+    }
+  else
+    {
+      Trc_PRT_shsem_hyshsem_setVal_Exit (rc);
+    }
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_close
+/**
+ * Release the resources allocated for the semaphore handles.
+ * 
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Semaphore set handle.
+ * 
+ * @note The actual semaphore is not destroyed.  Once the close operation has been performed 
+ * on the semaphore handle, it is no longer valid and user needs to reissue @ref hyshsem_open call.
+ */
+void VMCALL
+hyshsem_close (struct HyPortLibrary *portLibrary,
+               struct hyshsem_handle **handle)
+{
+  Trc_PRT_shsem_hyshsem_close_Entry (*handle);
+  /* On Unix you don't need to close the semaphore handles */
+  if (NULL == *handle)
+    {
+      return;
+    }
+  portLibrary->mem_free_memory (portLibrary, (*handle)->baseFile);
+  portLibrary->mem_free_memory (portLibrary, *handle);
+  *handle = NULL;
+  Trc_PRT_shsem_hyshsem_close_Exit ();
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_destroy
+/**
+ * Destroy the semaphore and release the resources allocated for the semaphore handles.
+ * 
+ * @param[in] portLibrary The port library.
+ * @param[in] handle Semaphore set handle.
+ * 
+ * @return 0 on success, -1 on failure.
+ * @note Due to operating system restriction we may not be able to destroy the semaphore
+ */
+IDATA VMCALL
+hyshsem_destroy (struct HyPortLibrary * portLibrary,
+                 struct hyshsem_handle ** handle)
+{
+  /*pre: user has not closed the handle, and assume user has perm to remove */
+  IDATA rc, rcunlink;
+
+  Trc_PRT_shsem_hyshsem_destroy_Entry (*handle);
+  if (*handle == NULL)
+    {
+      return SUCCESS;
+    }
+
+  if (semctl ((*handle)->semid, 0, IPC_RMID, 0))
+    {
+      /* EINVAL is okay - we just had a reboot so the semaphore id is no good */
+      if (errno != EINVAL)
+        {
+          rc = -1;
+        }
+    }
+  else
+    {
+      rc = 0;
+    }
+
+  rcunlink = portLibrary->file_unlink (portLibrary, (*handle)->baseFile);
+
+  Trc_PRT_shsem_hyshsem_destroy_Debug1 ((*handle)->baseFile, rcunlink, errno);
+
+  hyshsem_close (portLibrary, handle);
+
+  if (rc = 0)
+    {
+      Trc_PRT_shsem_hyshsem_destroy_Exit ();
+    }
+  else
+    {
+      Trc_PRT_shsem_hyshsem_destroy_Exit1 ();
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_startup
+/**
+ * PortLibrary startup.
+ *
+ * This function is called during startup of the portLibrary.  Any resources that are required for
+ * the file operations may be created here.  All resources created here should be destroyed
+ * in @ref hyshsem_shutdown.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @return 0 on success, negative error code on failure.  Error code values returned are
+ * \arg HYPORT_ERROR_STARTUP_SHSEM
+ *
+ * @note Most implementations will simply return success.
+ */
+I_32 VMCALL
+hyshsem_startup (struct HyPortLibrary * portLibrary)
+{
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyshsem_shutdown
+/**
+ * PortLibrary shutdown.
+ *
+ * This function is called during shutdown of the portLibrary.  Any resources that were created by @ref hyshsem_startup
+ * should be destroyed here.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @note Most implementations will be empty.
+ */
+void VMCALL
+hyshsem_shutdown (struct HyPortLibrary *portLibrary)
+{
+  /* Don't need to do anything for now, but maybe we will need to clean up
+   * some directories, etc over here.
+   */
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION createbaseFile
+static IDATA
+createbaseFile (struct HyPortLibrary *portLibrary, char *filename)
+{
+  IDATA fd;
+  I_32 flags = HyOpenCreate | HyOpenWrite | HyOpenCreateNew;
+
+  fd =
+    portLibrary->file_open (portLibrary, filename, flags, HYSH_BASEFILEPERM);
+
+  if (fd == -1)
+    {
+      I_32 errorno = portLibrary->error_last_error_number (portLibrary);
+
+      if (HYPORT_ERROR_FILE_EXIST == errorno)
+        {
+          return errorno;
+        }
+
+      return CREATE_ERROR;
+    }
+
+  portLibrary->file_close (portLibrary, fd);
+  return SUCCESS;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION writebaseFile
+static IDATA
+writebaseFile (struct HyPortLibrary *portLibrary, char *filename, int proj_id,
+               key_t key, int semid, int setSize)
+{
+  I_32 fd, rc, flags, perm;
+  hyshsem_baseFileFormat info;
+
+  flags = HyOpenWrite | HyOpenTruncate;
+  perm = HYSH_BASEFILEPERM;
+
+  fd = portLibrary->file_open (portLibrary, filename, flags, perm);
+  if (-1 == fd)
+    {
+      return OPEN_ERROR;
+    }
+
+  info.version = HYSH_VERSION;
+  info.modlevel = HYSH_MODLEVEL;
+  info.proj_id = proj_id;
+  info.ftok_key = key;
+  info.semid = semid;
+  info.creator_pid = portLibrary->sysinfo_get_pid (portLibrary);
+  info.semsetSize = setSize;
+
+  rc =
+    portLibrary->file_write (portLibrary, fd, &info,
+                             sizeof (hyshsem_baseFileFormat));
+  if (rc < 0)
+    {
+      rc = WRITE_ERROR;
+    }
+  else
+    {
+      rc = SUCCESS;
+    }
+
+  portLibrary->file_close (portLibrary, fd);
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION readbaseFile
+static IDATA
+readbaseFile (struct HyPortLibrary *portLibrary, char *filename,
+              hyshsem_baseFileFormat ** basefileInfo)
+{
+  I_32 fd, rc;
+  hyshsem_baseFileFormat *info;
+
+  fd = portLibrary->file_open (portLibrary, filename, HyOpenRead, 0);
+  if (-1 == fd)
+    {
+      return OPEN_ERROR;
+    }
+
+  info =
+    portLibrary->mem_allocate_memory (portLibrary,
+                                      sizeof (hyshsem_baseFileFormat));
+  if (info == NULL)
+    {
+      /* malloc failure! */
+      return MALLOC_ERROR;
+    }
+
+  rc =
+    portLibrary->file_read (portLibrary, fd, info,
+                            sizeof (hyshsem_baseFileFormat));
+
+  if (rc == 0)
+    {
+      rc = HYSH_NO_DATA;
+    }
+  else if (rc < 0)
+    {
+      rc = READ_ERROR;
+    }
+  else if (rc < sizeof (struct hyshsem_baseFileFormat))
+    {
+      rc = HYSH_BAD_DATA;
+    }
+  else
+    {
+      rc = SUCCESS;
+    }
+
+  portLibrary->file_close (portLibrary, fd);
+
+  if (rc != SUCCESS)
+    {
+      portLibrary->mem_free_memory (portLibrary, info);
+      *basefileInfo = NULL;
+    }
+  else
+    {
+      *basefileInfo = info;
+    }
+
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION createsemHandle
+static hyshsem_handle *
+createsemHandle (struct HyPortLibrary *portLibrary, int semid, int nsems,
+                 char *baseFile)
+{
+  hyshsem_handle *result;
+  IDATA baseFileLength = strlen (baseFile) + 1;
+
+  result =
+    portLibrary->mem_allocate_memory (portLibrary, sizeof (hyshsem_handle));
+  if (result == NULL)
+    {
+      return NULL;              /* malloc error! */
+    }
+
+  result->semid = semid;
+  result->nsems = nsems;
+
+  result->baseFile =
+    portLibrary->mem_allocate_memory (portLibrary, baseFileLength);
+  if (result == NULL)
+    {
+      portLibrary->mem_free_memory (portLibrary, result);
+      return NULL;
+    }
+
+  portLibrary->str_printf (portLibrary, result->baseFile, baseFileLength,
+                           "%s", baseFile);
+  return result;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION setMarker
+static I_32
+setMarker (hyshsem_handle * handle, int semsetsize)
+{
+  union semun sem_union;
+  if (NULL == handle)
+    {
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+
+  sem_union.val = SEMMARKER;
+  return semctl (handle->semid, semsetsize, SETVAL, sem_union);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION checkMarker
+static IDATA
+checkMarker (hyshsem_handle * handle, int semsetsize)
+{
+  IDATA rc;
+
+  if (handle == NULL)
+    {
+      return HYPORT_ERROR_SHSEM_HANDLE_INVALID;
+    }
+
+  rc = semctl (handle->semid, semsetsize, GETVAL);
+  if (rc == -1)
+    {
+      /* can't getval, so return failed */
+      return 0;
+    }
+
+  return rc == SEMMARKER;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION createSemaphore
+static IDATA
+createSemaphore (struct HyPortLibrary *portLibrary, char *baseFile,
+                 I_32 setSize, hyshsem_handle ** handle)
+{
+  IDATA rc;
+  int projid = 1;
+  key_t fkey;
+  int semid;
+  int semflags =
+    portLibrary->portGlobals->control.
+    shmem_group_perm ? HYSHSEM_SEMFLAGS_GROUP : HYSHSEM_SEMFLAGS;
+
+  /* base file not exist, so create it now */
+  rc = createbaseFile (portLibrary, baseFile);
+
+  /*
+   * TODO: Here we are rely on port layer not to mess around with errno
+   * we need a proper mechanism to return error code from port layer
+   */
+  if (HYPORT_ERROR_FILE_EXIST == rc)
+    {
+      /* creation race condition - need to go back to stat */
+      return RETRY;
+    }
+  else if (rc == CREATE_ERROR)
+    {
+      return FAILED;
+    }
+
+  /*sucessfully created base file, now create semaphores */
+
+  while (projid < HYSH_MAX_PROJ_ID)
+    {
+      /* first ftok to get key */
+      fkey = ftok (baseFile, projid);
+
+      if (fkey == -1)
+        {
+          if (errno == ENOENT || errno == ENOTDIR)
+            {
+              /*
+               * race condition: another JVM tries to clean up
+               * while we trying to connect to it
+               * just return and ask caller to retry
+               */
+              return RETRY;
+            }
+          return FAILED;
+        }
+
+#if defined(HYSHSEM_DEBUG)
+      portLibrary->tty_printf (portLibrary,
+                               "creating semaphore, setSize = %d\n",
+                               setSize + 1);
+#endif
+
+      /* 
+       * Notice that we create with setSize+1 - we create an extra semaphore
+       * so that we can put a "Marker" in there to say this is one of us 
+       */
+      semid = semget (fkey, setSize + 1, semflags);
+
+      if (semid == -1)
+        {
+          if (errno == EEXIST)
+            {
+              /* EEXIST means that there is a semaphore key that's already being used.
+               * It could means that someone has delete the semaphore control file
+               * and as a result we couldn't reopen the semaphore
+               * We should just bumped the projid, which will give us a different
+               * key and we can try to create again.
+               */
+              projid++;
+              continue;
+            }
+
+          portLibrary->error_set_last_error (portLibrary, errno,
+                                             findError (errno, __errno2 ()));
+          return FAILED;
+        }
+      /* if we get here it means that we have succes with getting a semaphore! */
+      break;
+    }
+
+  if (semid == -1)
+    {
+      /* 
+       * If we get here it means that we have tried to ftok for a while and still can't get a unique id
+       * tell user and return
+       */
+      return FAILED;
+    }
+
+  *handle = createsemHandle (portLibrary, semid, setSize, baseFile);
+  if (*handle == NULL)
+    {
+      return FAILED;
+    }
+
+  /* set the last value with our marker */
+  rc = setMarker (*handle, setSize);
+
+  rc = writebaseFile (portLibrary, baseFile, projid, fkey, semid, setSize);
+  if (rc != SUCCESS)
+    {
+      /*failed to write base file - fatal! */
+      return FAILED;
+    }
+
+  /* set the timestamp */
+  (*handle)->timestamp = portLibrary->file_lastmod (portLibrary, baseFile);
+
+  return SEMAPHORE_CREATED;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION openSemaphore
+static IDATA
+openSemaphore (struct HyPortLibrary *portLibrary, char *baseFile,
+               I_64 timestamp, hyshsem_handle ** handle)
+{
+  /* base file exist - process the file and get sem info */
+  hyshsem_baseFileFormat *info;
+  I_8 retrycount = RETRY_COUNT;
+  key_t fkey;
+  I_32 rc;
+
+  while (retrycount > 0)
+    {
+
+      rc = readbaseFile (portLibrary, baseFile, &info);
+      switch (rc)
+        {
+        case OPEN_ERROR:
+          return FAILED;
+        case READ_ERROR:
+          return RETRY;
+        case HYSH_BAD_DATA:
+          /* basefile info bad! */
+          return FAILED;
+        case HYSH_NO_DATA:
+          /* retry? if file empty */
+          usleep (SLEEP_TIME);
+          retrycount--;
+          break;
+        default:
+          /*basefile info OK, stop retrying */
+          retrycount = 0;
+          break;
+        }
+    }                           /* end while */
+
+  if (info == NULL)
+    {
+      /*retry already but still can't get data */
+      if (portLibrary->file_unlink (portLibrary, baseFile) != 0)
+        {
+          return FAILED;
+        }
+      return RETRY;
+    }
+
+  /* check that the modlevel and version is okay */
+  if (info->version != HYSH_VERSION || info->modlevel != HYSH_MODLEVEL)
+    {
+      return FAILED;
+    }
+
+  *handle =
+    createsemHandle (portLibrary, info->semid, info->semsetSize, baseFile);
+
+  (*handle)->timestamp = timestamp;
+
+  /* need to see whether the semid is still valid */
+  if (!checkMarker (*handle, info->semsetSize))
+    {
+      /* we had a reboot, and as a result semaphore ID is not valid */
+      /* Just report to the user - we should not try to recover from here */
+      rc = HYPORT_INFO_SHSEM_SEMID_DIFF;
+    }
+  else
+    {
+      rc = SEMAPHORE_OPENED;
+    }
+
+  portLibrary->mem_free_memory (portLibrary, info);
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION findError
+/**
+ * @internal
+ * Determines the proper portable error code to return given a native error code
+ *
+ * @param[in] errorCode The error code reported by the OS
+ *
+ * @return	the (negative) portable error code
+ */
+static I_32
+findError (I_32 errorCode, I_32 errorCode2)
+{
+  switch (errorCode)
+    {
+    case EPERM:
+    case EACCES:
+      return HYPORT_ERROR_SHSEM_NOPERMISSION;
+    case EEXIST:
+      return HYPORT_ERROR_SHSEM_ALREADY_EXIST;
+    case ENOMEM:
+    case ENOSPC:
+    case EMFILE:
+      return HYPORT_ERROR_SHSEM_NOSPACE;
+    case ENOENT:
+    case EINVAL:
+    default:
+      return HYPORT_ERROR_SHSEM_OPFAILED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.h?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hyshsem.h Wed Nov 30 21:29:27 2005
@@ -0,0 +1,58 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(hyshsem_h)
+#define hyshsem_h
+#include <sys/types.h>
+#include <errno.h>
+#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun
+{
+  int val;                      /* value for SETVAL */
+  struct semid_ds *buf;         /* buffer for IPC_STAT, IPC_SET */
+  unsigned short int *array;    /* array for GETALL, SETALL */
+  struct seminfo *__buf;        /* buffer for IPC_INFO */
+};
+#endif
+/* This is the control file contents */
+typedef struct hyshsem_baseFileFormat
+{
+  I_32 version;
+  I_32 modlevel;
+  I_32 timeout;
+  I_32 proj_id;
+  key_t ftok_key;
+  I_32 semid;
+  I_32 creator_pid;
+  I_32 semsetSize;
+} hyshsem_baseFileFormat;
+typedef struct hyshsem_handle
+{
+  I_32 semid;
+  I_32 nsems;
+  char *baseFile;
+  I_64 timestamp;
+  I_32 baseFilefd;
+  /* TODO: do we need the length of baseFile? */
+} hyshsem_handle;
+#define HYSHSEM_SEMFLAGS (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)
+#define HYSHSEM_SEMFLAGS_GROUP (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
+#define HYSHSEM_SEMMARKER 769
+/* for zOS we have a function to get extended error code - useful for debugging */
+#define __errno2() 0
+#endif /* hyshsem_h */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysignal.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysignal.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysignal.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysignal.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,1484 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hyport.h"
+#include "hythread.h"
+#include <signal.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <semaphore.h>
+
+#include <jsig.h>
+
+#define __USE_GNU
+#include <dlfcn.h>
+#undef __USE_GNU
+
+#define MAX_PORTLIB_SIGNAL_TYPES  8
+#define MAX_UNIX_SIGNAL_TYPES  _NSIG
+
+typedef void (*linux386_sigaction) (int, siginfo_t *, void *);
+
+/* Store the previous signal handlers, we need to restore them when we're done */
+static struct
+{
+  struct sigaction action;
+  U_32 restore;
+} oldActions[MAX_UNIX_SIGNAL_TYPES];
+
+/* record the signals for which we have registered a master handler
+ * access to this must be protected with by masterHandlerMonitor */
+static U_32 signalsWithMasterHandlers;
+static U_32 shutDownASynchReporter;
+
+static U_32 attachedPortLibraries;
+
+typedef struct HyLinux386AsyncHandlerRecord
+{
+  HyPortLibrary *portLib;
+  hysig_handler_fn handler;
+  void *handler_arg;
+  U_32 flags;
+  struct HyLinux386AsyncHandlerRecord *next;
+} HyLinux386AsyncHandlerRecord;
+
+/* holds the options set by hysig_set_options */
+static U_32 signalOptions;
+
+static HyLinux386AsyncHandlerRecord *asyncHandlerList;
+
+static sem_t wakeUpASynchReporter;
+static sem_t sigQuitPendingSem;
+static sem_t sigAbrtPendingSem;
+static sem_t sigTermPendingSem;
+static sem_t sigReconfigPendingSem;
+
+static hythread_monitor_t asyncMonitor;
+static hythread_monitor_t masterHandlerMonitor;
+static hythread_monitor_t asyncReporterShutdownMonitor;
+static U_32 asyncThreadCount;
+static U_32 attachedPortLibraries;
+
+typedef struct HyLinux386SignalInfo
+{
+  U_32 portLibrarySignalType;
+  void *handlerAddress;
+  void *handlerAddress2;
+  struct sigcontext *sigContext;
+  siginfo_t *sigInfo;
+  Dl_info dl_info;
+} HyLinux386SignalInfo;
+
+struct HySignalHandlerRecord
+{
+  struct HySignalHandlerRecord *previous;
+  struct HyPortLibrary *portLibrary;
+  hysig_handler_fn handler;
+  void *handler_arg;
+  sigjmp_buf returnBuf;
+  U_32 flags;
+};
+
+typedef struct HyCurrentSignal
+{
+  int signal;
+  siginfo_t *sigInfo;
+  void *contextInfo;
+} HyCurrentSignal;
+
+/* key to get the end of the synchronous handler records */
+static hythread_tls_key_t tlsKey;
+
+/* key to get the current synchronous signal */
+static hythread_tls_key_t tlsKeyCurrentSignal;
+
+struct
+{
+  U_32 portLibSignalNo;
+  U_32 unixSignalNo;
+} signalMap[] =
+{
+  {
+  HYPORT_SIG_FLAG_SIGSEGV, SIGSEGV},
+  {
+  HYPORT_SIG_FLAG_SIGBUS, SIGBUS},
+  {
+  HYPORT_SIG_FLAG_SIGILL, SIGILL},
+  {
+  HYPORT_SIG_FLAG_SIGFPE, SIGFPE},
+  {
+  HYPORT_SIG_FLAG_SIGTRAP, SIGTRAP},
+  {
+  HYPORT_SIG_FLAG_SIGQUIT, SIGQUIT},
+  {
+  HYPORT_SIG_FLAG_SIGABRT, SIGABRT},
+  {
+  HYPORT_SIG_FLAG_SIGTERM, SIGTERM}
+};
+
+/* the number of xmm registers */
+#define NXMMREGS 8
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+
+static U_32 destroySignalTools (HyPortLibrary * portLibrary);
+
+static U_32 infoForFPR (struct HyPortLibrary *portLibrary,
+                        struct HyLinux386SignalInfo *info, I_32 index,
+                        const char **name, void **value);
+
+static void masterSynchSignalHandler (int signal, siginfo_t * sigInfo,
+                                      void *contextInfo);
+
+static U_32 infoForGPR (struct HyPortLibrary *portLibrary,
+                        struct HyLinux386SignalInfo *info, I_32 index,
+                        const char **name, void **value);
+
+static void removeAsyncHandlers (HyPortLibrary * portLibrary);
+
+static U_32 mapPortLibSignalToUnix (U_32 portLibSignal);
+
+static U_32 mapUnixSignalToPortLib (U_32 signalNo, siginfo_t * sigInfo);
+
+static U_32 infoForSignal (struct HyPortLibrary *portLibrary,
+                           struct HyLinux386SignalInfo *info, I_32 index,
+                           const char **name, void **value);
+
+static void fillInLinux386SignalInfo (struct HyPortLibrary *portLibrary,
+                                      U_32 portLibSignalType,
+                                      hysig_handler_fn handler,
+                                      siginfo_t * signalInfo,
+                                      void *contextInfo,
+                                      struct HyLinux386SignalInfo *hyinfo);
+
+static U_32 infoForModule (struct HyPortLibrary *portLibrary,
+                           struct HyLinux386SignalInfo *info, I_32 index,
+                           const char **name, void **value);
+
+static I_32 registerMasterHandlers (HyPortLibrary * portLibrary, U_32 flags,
+                                    U_32 allowedSubsetOfFlags);
+
+static U_32 countInfoInCategory (struct HyPortLibrary *portLibrary,
+                                 void *info, U_32 category);
+
+static void VMCALL sig_full_shutdown (struct HyPortLibrary *portLibrary);
+
+static U_32 initializeSignalTools (HyPortLibrary * portLibrary);
+
+static void masterASynchSignalHandler (int signal, siginfo_t * sigInfo,
+                                       void *contextInfo);
+
+static int HYTHREAD_PROC asynchSignalReporter (void *userData);
+
+static U_32 infoForControl (struct HyPortLibrary *portLibrary,
+                            struct HyLinux386SignalInfo *info, I_32 index,
+                            const char **name, void **value);
+
+static U_32 registerSignalHandlerWithOS (HyPortLibrary * portLibrary,
+                                         U_32 portLibrarySignalNo,
+                                         linux386_sigaction handler);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_can_protect
+I_32 VMCALL
+hysig_can_protect (struct HyPortLibrary *portLibrary, U_32 flags)
+{
+  U_32 supportedFlags =
+    HYPORT_SIG_FLAG_MAY_RETURN | HYPORT_SIG_FLAG_MAY_CONTINUE_EXECUTION;
+
+  if (0 == (signalOptions & HYPORT_SIG_OPTIONS_REDUCED_SIGNALS))
+    {
+      supportedFlags |=
+        HYPORT_SIG_FLAG_SIGALLSYNC | HYPORT_SIG_FLAG_SIGQUIT |
+        HYPORT_SIG_FLAG_SIGABRT | HYPORT_SIG_FLAG_SIGTERM;
+    }
+
+  if ((flags & supportedFlags) == flags)
+    {
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_info
+U_32 VMCALL
+hysig_info (struct HyPortLibrary * portLibrary, void *info, U_32 category,
+            I_32 index, const char **name, void **value)
+{
+  *name = "";
+
+  switch (category)
+    {
+    case HYPORT_SIG_SIGNAL:
+      return infoForSignal (portLibrary, info, index, name, value);
+    case HYPORT_SIG_GPR:
+      return infoForGPR (portLibrary, info, index, name, value);
+    case HYPORT_SIG_CONTROL:
+      return infoForControl (portLibrary, info, index, name, value);
+    case HYPORT_SIG_MODULE:
+      return infoForModule (portLibrary, info, index, name, value);
+    case HYPORT_SIG_FPR:
+      return infoForFPR (portLibrary, info, index, name, value);
+    case HYPORT_SIG_OTHER:
+
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_info_count
+U_32 VMCALL
+hysig_info_count (struct HyPortLibrary * portLibrary, void *info,
+                  U_32 category)
+{
+  return countInfoInCategory (portLibrary, info, category);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_protect
+/**
+ * We register the master signal handlers here to deal with -Xrs
+ */
+I_32 VMCALL
+hysig_protect (struct HyPortLibrary * portLibrary, hysig_protected_fn fn,
+               void *fn_arg, hysig_handler_fn handler, void *handler_arg,
+               U_32 flags, UDATA * result)
+{
+
+  struct HySignalHandlerRecord thisRecord;
+  hythread_t thisThread;
+  U_32 rc;
+  U_32 allowHandlers;
+
+  hythread_monitor_enter (masterHandlerMonitor);
+  if (HYPORT_SIG_OPTIONS_REDUCED_SIGNALS & signalOptions)
+    {
+      /* -Xrs was set, we can't protect against any signals, do not install the master handler */
+      allowHandlers = 0;
+    }
+  else
+    {
+      allowHandlers = 1;
+      rc =
+        registerMasterHandlers (portLibrary, flags,
+                                HYPORT_SIG_FLAG_SIGALLSYNC);
+    }
+  hythread_monitor_exit (masterHandlerMonitor);
+
+  if (allowHandlers)
+    {
+
+      if (rc)
+        {
+          return HYPORT_SIG_ERROR;
+        }
+
+      thisThread = hythread_self ();
+
+      thisRecord.previous = hythread_tls_get (thisThread, tlsKey);
+      thisRecord.portLibrary = portLibrary;
+      thisRecord.handler = handler;
+      thisRecord.handler_arg = handler_arg;
+      thisRecord.flags = flags;
+
+      if (flags & HYPORT_SIG_FLAG_MAY_RETURN)
+        {
+
+          /* setjmp/longjmp does not clear the mask setup by the OS when it delivers the signal. Use sigsetjmp/siglongjmp(buf, 1) instead */
+          if (sigsetjmp (thisRecord.returnBuf, 1))
+            {
+
+              /* the handler had long jumped back here -- reset the signal handler stack and return */
+              hythread_tls_set (thisThread, tlsKey, thisRecord.previous);
+              *result = 0;
+              /* Trc_PRT_signal_hysignal_sigProtect_Exit_exception(); */
+              return HYPORT_SIG_EXCEPTION_OCCURRED;
+            }
+        }
+
+      if (hythread_tls_set (thisThread, tlsKey, &thisRecord))
+        {
+          /* Trc_PRT_signal_hysignal_sigProtect_Exit2_error(); */
+          return HYPORT_SIG_ERROR;
+        }
+
+    }                           /* end if allowHandlers */
+
+  *result = fn (portLibrary, fn_arg);
+
+  /* if the first hythread_tls_set succeeded, then this one will always succeed */
+  hythread_tls_set (thisThread, tlsKey, thisRecord.previous);
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_set_async_signal_handler
+U_32 VMCALL
+hysig_set_async_signal_handler (struct HyPortLibrary * portLibrary,
+                                hysig_handler_fn handler, void *handler_arg,
+                                U_32 flags)
+{
+
+  U_32 rc = 0;
+  U_32 signalsRegisteredWithOS = 0;
+  HyLinux386AsyncHandlerRecord *cursor;
+  HyLinux386AsyncHandlerRecord **previousLink;
+
+  hythread_monitor_enter (masterHandlerMonitor);
+  if (HYPORT_SIG_OPTIONS_REDUCED_SIGNALS & signalOptions)
+    {
+      /* -Xrs was set, we can't protect against any signals, do not install any handlers */
+      rc = -1;
+    }
+  else
+    {
+      rc =
+        registerMasterHandlers (portLibrary, flags,
+                                HYPORT_SIG_FLAG_SIGALLASYNC);
+    }
+  hythread_monitor_exit (masterHandlerMonitor);
+
+  if (rc)
+    {
+      return HYPORT_SIG_ERROR;
+    }
+
+  hythread_monitor_enter (asyncMonitor);
+
+  /* wait until no signals are being reported */
+  while (asyncThreadCount > 0)
+    {
+      hythread_monitor_wait (asyncMonitor);
+    }
+
+  /* is this handler already registered? */
+  previousLink = &asyncHandlerList;
+  cursor = asyncHandlerList;
+
+  while (cursor)
+    {
+      if ((cursor->portLib == portLibrary) && (cursor->handler == handler)
+          && (cursor->handler_arg == handler_arg))
+        {
+          if (flags == 0)
+            {
+              /* remove this handler record */
+              *previousLink = cursor->next;
+              portLibrary->mem_free_memory (portLibrary, cursor);
+
+            }
+          else
+            {
+              /* update the listener with the new flags */
+              cursor->flags = flags;
+            }
+          break;
+        }
+      previousLink = &cursor->next;
+      cursor = cursor->next;
+    }
+
+  if (cursor == NULL)
+    {
+      /* cursor will only be NULL if we failed to find it in the list */
+      if (flags != 0)
+        {
+          HyLinux386AsyncHandlerRecord *record =
+            portLibrary->mem_allocate_memory (portLibrary, sizeof (*record));
+
+          if (record == NULL)
+            {
+              rc = 1;
+            }
+          else
+            {
+              record->portLib = portLibrary;
+              record->handler = handler;
+              record->handler_arg = handler_arg;
+              record->flags = flags;
+              record->next = NULL;
+
+              /* add the new record to the end of the list */
+              *previousLink = record;
+            }
+        }
+    }
+
+  hythread_monitor_exit (asyncMonitor);
+
+  return rc;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_shutdown
+/*
+ * The full shutdown routine "sig_full_shutdown" overwrites this once we've completed startup 
+ */
+void VMCALL
+hysig_shutdown (struct HyPortLibrary *portLibrary)
+{
+  return;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_startup
+/**
+ * Start up the signal handling component of the port library
+ *
+ * Note: none of the master handlers are registered with the OS until the first call to either of hysig_protect or hysig_set_async_signal_handler
+ * Note: the async reporting thread is not started up until the first call to hysig_set_asyc_signal_handler 
+*/
+
+I_32 VMCALL
+hysig_startup (struct HyPortLibrary * portLibrary)
+{
+
+  I_32 result = 0;
+
+  hythread_monitor_t globalMonitor = hythread_global_monitor ();
+  U_32 index;
+
+  hythread_monitor_enter (globalMonitor);
+  if (attachedPortLibraries++ == 0)
+    {
+
+      /* initialize the old actions */
+      for (index = 0; index < MAX_UNIX_SIGNAL_TYPES; index++)
+        {
+          oldActions[index].restore = 0;
+        }
+
+      result = initializeSignalTools (portLibrary);
+
+    }
+  hythread_monitor_exit (globalMonitor);
+
+  if (result == 0)
+    {
+      /* we have successfully started up the signal portion, install the full shutdown routine */
+      portLibrary->sig_shutdown = sig_full_shutdown;
+    }
+
+  return result;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION countInfoInCategory
+
+static U_32
+countInfoInCategory (struct HyPortLibrary *portLibrary, void *info,
+                     U_32 category)
+{
+  void *value;
+  const char *name;
+  U_32 count = 0;
+
+  while (portLibrary->
+         sig_info (portLibrary, info, category, count, &name,
+                   &value) != HYPORT_SIG_VALUE_UNDEFINED)
+    {
+      count++;
+    }
+
+  return count;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION infoForSignal
+
+static U_32
+infoForSignal (struct HyPortLibrary *portLibrary,
+               struct HyLinux386SignalInfo *info, I_32 index,
+               const char **name, void **value)
+{
+  *name = "";
+
+  switch (index)
+    {
+
+    case HYPORT_SIG_SIGNAL_TYPE:
+    case 0:
+      *name = "HyGeneric_Signal_Number";
+      *value = &info->portLibrarySignalType;
+      return HYPORT_SIG_VALUE_32;
+
+    case HYPORT_SIG_SIGNAL_PLATFORM_SIGNAL_TYPE:
+    case 1:
+      *name = "Signal_Number";
+      *value = &info->sigInfo->si_signo;
+      return HYPORT_SIG_VALUE_32;
+
+    case HYPORT_SIG_SIGNAL_ERROR_VALUE:
+    case 2:
+      *name = "Error_Value";
+      *value = &info->sigInfo->si_errno;
+      return HYPORT_SIG_VALUE_32;
+
+    case HYPORT_SIG_SIGNAL_CODE:
+    case 3:
+      *name = "Signal_Code";
+      *value = &info->sigInfo->si_code;
+      return HYPORT_SIG_VALUE_32;
+
+    case HYPORT_SIG_SIGNAL_HANDLER:
+    case 4:
+      *name = "Handler1";
+      *value = &info->handlerAddress;
+      return HYPORT_SIG_VALUE_ADDRESS;
+
+    case 5:
+      *name = "Handler2";
+      *value = &info->handlerAddress2;
+      return HYPORT_SIG_VALUE_ADDRESS;
+
+    case HYPORT_SIG_SIGNAL_INACCESSIBLE_ADDRESS:
+    case 6:
+      /* si_code > 0 indicates that the signal was generated by the kernel */
+      if (info->sigInfo->si_code > 0)
+        {
+          if ((info->sigInfo->si_signo == SIGBUS)
+              || (info->sigInfo->si_signo == SIGSEGV))
+            {
+              *name = "InaccessibleAddress";
+              *value = &info->sigInfo->si_addr;
+              return HYPORT_SIG_VALUE_ADDRESS;
+            }
+        }
+      return HYPORT_SIG_VALUE_UNDEFINED;
+
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION infoForFPR
+
+static U_32
+infoForFPR (struct HyPortLibrary *portLibrary,
+            struct HyLinux386SignalInfo *info, I_32 index, const char **name,
+            void **value)
+{
+  static const char *n_xmm[] = {
+    "xmm0",
+    "xmm1",
+    "xmm2",
+    "xmm3",
+    "xmm4",
+    "xmm5",
+    "xmm6",
+    "xmm7"
+  };
+
+  switch (index)
+    {
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION infoForGPR
+
+static U_32
+infoForGPR (struct HyPortLibrary *portLibrary,
+            struct HyLinux386SignalInfo *info, I_32 index, const char **name,
+            void **value)
+{
+  *name = "";
+
+  switch (index)
+    {
+    case HYPORT_SIG_GPR_X86_EDI:
+    case 0:
+      *name = "EDI";
+      *value = &info->sigContext->edi;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_GPR_X86_ESI:
+    case 1:
+      *name = "ESI";
+      *value = &info->sigContext->esi;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_GPR_X86_EAX:
+    case 2:
+      *name = "EAX";
+      *value = &info->sigContext->eax;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_GPR_X86_EBX:
+    case 3:
+      *name = "EBX";
+      *value = &info->sigContext->ebx;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_GPR_X86_ECX:
+    case 4:
+      *name = "ECX";
+      *value = &info->sigContext->ecx;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_GPR_X86_EDX:
+    case 5:
+      *name = "EDX";
+      *value = &info->sigContext->edx;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION infoForControl
+
+static U_32
+infoForControl (struct HyPortLibrary *portLibrary,
+                struct HyLinux386SignalInfo *info, I_32 index,
+                const char **name, void **value)
+{
+  *name = "";
+  U_8 *eip;
+
+  switch (index)
+    {
+    case HYPORT_SIG_CONTROL_PC:
+    case 0:
+      *name = "EIP";
+      *value = (void *) &(info->sigContext->eip);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case 1:
+      *name = "ES";
+      *value = (void *) &(info->sigContext->es);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case 2:
+      *name = "DS";
+      *value = (void *) &(info->sigContext->ds);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_CONTROL_SP:
+    case 3:
+      *name = "ESP";
+      *value = (void *) &(info->sigContext->esp);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case 4:
+      *name = "EFlags";
+      *value = (void *) &(info->sigContext->eflags);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case 5:
+      *name = "CS";
+      *value = (void *) &(info->sigContext->cs);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case 6:
+      *name = "SS";
+      *value = (void *) &(info->sigContext->ss);
+      return HYPORT_SIG_VALUE_ADDRESS;
+    case HYPORT_SIG_CONTROL_BP:
+    case 7:
+      *name = "EBP";
+      *value = &info->sigContext->ebp;
+      return HYPORT_SIG_VALUE_ADDRESS;
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION infoForModule
+
+static U_32
+infoForModule (struct HyPortLibrary *portLibrary,
+               struct HyLinux386SignalInfo *info, I_32 index,
+               const char **name, void **value)
+{
+  void *address;
+  Dl_info *dl_info = &(info->dl_info);
+  *name = "";
+
+  address = (void *) info->sigContext->eip;
+  int dl_result = dladdr ((void *) info->sigContext->eip, dl_info);
+
+  switch (index)
+    {
+    case HYPORT_SIG_MODULE_NAME:
+    case 0:
+      *name = "Module";
+      if (dl_result)
+        {
+          *value = (void *) (dl_info->dli_fname);
+          return HYPORT_SIG_VALUE_STRING;
+        }
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    case 1:
+      *name = "Module_base_address";
+      if (dl_result)
+        {
+          *value = (void *) &(dl_info->dli_fbase);
+          return HYPORT_SIG_VALUE_ADDRESS;
+        }
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    case 2:
+      *name = "Symbol";
+      if (dl_result)
+        {
+          if (dl_info->dli_sname != NULL)
+            {
+              *value = (void *) (dl_info->dli_sname);
+              return HYPORT_SIG_VALUE_STRING;
+            }
+        }
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    case 3:
+      *name = "Symbol_address";
+      if (dl_result)
+        {
+          *value = (void *) &(dl_info->dli_saddr);
+          return HYPORT_SIG_VALUE_ADDRESS;
+        }
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    default:
+      return HYPORT_SIG_VALUE_UNDEFINED;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION masterExceptionHandler
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION fillInLinux386SignalInfo
+
+static void
+fillInLinux386SignalInfo (struct HyPortLibrary *portLibrary,
+                          U_32 portLibSignalType, hysig_handler_fn handler,
+                          siginfo_t * signalInfo, void *contextInfo,
+                          struct HyLinux386SignalInfo *hyinfo)
+{
+  struct sigcontext *sigContext;
+  ucontext_t *uContext;
+
+  uContext = (ucontext_t *) contextInfo;
+  sigContext = (struct sigcontext *) &uContext->uc_mcontext;
+  memset (hyinfo, 0, sizeof (*hyinfo));
+
+  hyinfo->portLibrarySignalType = portLibSignalType;
+  hyinfo->handlerAddress = (void *) handler;
+  hyinfo->handlerAddress2 = (void *) masterSynchSignalHandler;
+  hyinfo->sigContext = sigContext;
+  hyinfo->sigInfo = signalInfo;
+  /* module info is filled on demand */
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION asynchSignalReporter
+
+/**
+ * Reports the asynchronous signal to all listeners.
+ */
+static int HYTHREAD_PROC
+asynchSignalReporter (void *userData)
+{
+  U_32 type;
+  HyLinux386AsyncHandlerRecord *cursor;
+  U_32 result = FALSE;
+  U_32 asyncSignalFlag = 0;
+
+  /* Trc_PRT_signal_hysignal_asynchSignalReporter_Entry(signal); */
+
+  /* Need an exit condition... */
+  for (;;)
+    {
+      sem_wait (&wakeUpASynchReporter);
+
+      /* we get woken up if there is a signal pending or it is time to shutdown */
+      if (shutDownASynchReporter)
+        {
+          break;
+        }
+
+      /* determine which signal we've being woken up for */
+      if (!sem_trywait (&sigQuitPendingSem))
+        {
+          asyncSignalFlag = HYPORT_SIG_FLAG_SIGQUIT;
+        }
+      else if (!sem_trywait (&sigAbrtPendingSem))
+        {
+          asyncSignalFlag = HYPORT_SIG_FLAG_SIGABRT;
+        }
+      else if (!sem_trywait (&sigTermPendingSem))
+        {
+          asyncSignalFlag = HYPORT_SIG_FLAG_SIGTERM;
+        }
+
+      /* report this signal to all of it's handlers */
+
+      /* incrementing the asyncThreadCount will prevent the list from being modified while we use it */
+      hythread_monitor_enter (asyncMonitor);
+      asyncThreadCount++;
+      hythread_monitor_exit (asyncMonitor);
+
+      cursor = asyncHandlerList;
+      while (cursor)
+        {
+          if (cursor->flags & asyncSignalFlag)
+            {
+              cursor->handler (cursor->portLib, asyncSignalFlag, NULL,
+                               cursor->handler_arg);
+              result = TRUE;
+            }
+          cursor = cursor->next;
+        }
+
+      hythread_monitor_enter (asyncMonitor);
+      if (--asyncThreadCount == 0)
+        {
+          hythread_monitor_notify_all (asyncMonitor);
+        }
+      hythread_monitor_exit (asyncMonitor);
+
+      if (!(signalOptions & HYPORT_SIG_OPTIONS_JSIG_NO_CHAIN))
+        {
+          jsig_handler (mapPortLibSignalToUnix (asyncSignalFlag), NULL, NULL);
+        }
+
+      /* reset the signal store */
+      asyncSignalFlag = 0;
+    }
+
+  hythread_monitor_enter (asyncReporterShutdownMonitor);
+  shutDownASynchReporter = 0;
+  hythread_monitor_notify (asyncReporterShutdownMonitor);
+
+  hythread_exit (asyncReporterShutdownMonitor);
+
+  /* unreachable */
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION masterSynchSignalHandler
+
+/**
+ * This signal handler is specific to synchronous signals.
+ * It will call all of the user's handlers that were registered with the vm using hysig_protect, 
+ * upon receiving a signal they listen for.
+ *
+ */
+static void
+masterSynchSignalHandler (int signal, siginfo_t * sigInfo, void *contextInfo)
+{
+  U_32 portLibType;
+  struct HySignalHandlerRecord *thisRecord;
+  struct HyCurrentSignal currentSignal;
+  struct HyCurrentSignal *previousSignal;
+  hythread_t thisThread = hythread_self ();
+
+  thisRecord = NULL;
+
+  /* Trc_PRT_signal_hysignal_masterHandler_Entry(signal, sigInfo, contextInfo); */
+  portLibType = mapUnixSignalToPortLib (signal, sigInfo);
+
+  /* record this signal in tls so that jsig_handler can be called if any of the handlers decide we should be shutting down */
+  currentSignal.signal = signal;
+  currentSignal.sigInfo = sigInfo;
+  currentSignal.contextInfo = contextInfo;
+
+  previousSignal = hythread_tls_get (thisThread, tlsKeyCurrentSignal);
+
+  hythread_tls_set (thisThread, tlsKeyCurrentSignal, &currentSignal);
+
+  /* walk the stack of registered handlers from top to bottom searching for one which handles this type of exception */
+  thisRecord = hythread_tls_get (thisThread, tlsKey);
+
+  while (thisRecord)
+    {
+      if (thisRecord->flags & portLibType)
+        {
+          struct HyLinux386SignalInfo hyinfo;
+          U_32 result;
+
+          /* found a suitable handler */
+          /* what signal type do we want to pass on here? port or platform based ? */
+          fillInLinux386SignalInfo (thisRecord->portLibrary, portLibType,
+                                    thisRecord->handler, sigInfo, contextInfo,
+                                    &hyinfo);
+
+          /* remove the handler we are about to invoke, now, in case the handler crashes */
+          hythread_tls_set (thisThread, tlsKey, thisRecord->previous);
+
+          result =
+            thisRecord->handler (thisRecord->portLibrary, portLibType,
+                                 &hyinfo, thisRecord->handler_arg);
+
+          /* The only case in which we don't want the previous handler back on top is if it just returned HYPORT_SIG_EXCEPTION_RETURN
+           *              In this case we will remove it from the top after executing the siglongjmp */
+          hythread_tls_set (thisThread, tlsKey, thisRecord);
+
+          if (result == HYPORT_SIG_EXCEPTION_CONTINUE_SEARCH)
+            {
+              /* continue looping */
+            }
+          else if (result == HYPORT_SIG_EXCEPTION_CONTINUE_EXECUTION)
+            {
+              hythread_tls_set (thisThread, tlsKeyCurrentSignal,
+                                previousSignal);
+              return;
+            }
+          else                  /* if (result == HYPORT_SIG_EXCEPTION_RETURN) */
+            {
+              hythread_tls_set (thisThread, tlsKeyCurrentSignal,
+                                previousSignal);
+              siglongjmp (thisRecord->returnBuf, 0);              
+            }
+        }
+
+      thisRecord = thisRecord->previous;
+    }
+
+  if (!(signalOptions & HYPORT_SIG_OPTIONS_JSIG_NO_CHAIN))
+    {
+      int rc = jsig_handler (signal, (void *) sigInfo, contextInfo);
+      if ((JSIG_RC_DEFAULT_ACTION_REQUIRED == rc)
+          && (SI_USER != sigInfo->si_code))
+        {
+          abort ();
+        }
+    }
+
+  /* if we got this far there weren't any handlers on the stack that knew what to with this signal
+   * default action is to abort */
+  abort ();
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION masterASynchSignalHandler
+
+/** 
+ * Determines the signal received and notifies the asynch signal reporter
+ *
+ * One semaphore is used to notify the asynchronous signal reporter that it is time to act.
+ * Each expected aynch signal type has an associated semaphore which is used to count the number of "pending" signals.
+ *
+ */
+static void
+masterASynchSignalHandler (int signal, siginfo_t * sigInfo, void *contextInfo)
+{
+  U_32 portLibSignalType;
+  U_32 index = -1;
+
+  portLibSignalType = mapUnixSignalToPortLib (signal, sigInfo);
+
+  switch (portLibSignalType)
+    {
+    case HYPORT_SIG_FLAG_SIGQUIT:
+      sem_post (&sigQuitPendingSem);
+      break;
+    case HYPORT_SIG_FLAG_SIGABRT:
+      sem_post (&sigAbrtPendingSem);
+      break;
+    case HYPORT_SIG_FLAG_SIGTERM:
+      sem_post (&sigTermPendingSem);
+      break;
+    case HYPORT_SIG_FLAG_SIGRECONFIG:
+      sem_post (&sigReconfigPendingSem);
+      break;
+    }
+
+  /* Trc_PRT_signal_hysignal_AsynchSignalHandler_Entry(signal, sigInfo, contextInfo); */
+  sem_post (&wakeUpASynchReporter);
+
+  return;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION registerSignalHandlerWithOS
+
+/**
+ * Register the signal handler with the OS, generally used to register the master signal handlers 
+ * Not to be confused with hysig_protect, which registers the user's handler with the port library.
+ * 
+ * Calls to this function must be synchronized using "syncMonitor".
+ * 
+ * The use of this function forces the flags SA_RESTART | SA_SIGINFO | SA_NODEFER to be set for the new signal action
+ * 
+ * The old action for the signal handler is stored in oldActions. These must be restored before the portlibrary is shut down.
+ *
+ * @return 0 upon success, non-zero otherwise.
+ */
+static U_32
+registerSignalHandlerWithOS (HyPortLibrary * portLibrary,
+                             U_32 portLibrarySignalNo,
+                             linux386_sigaction handler)
+{
+  struct sigaction newAction;
+  U_32 unixSignalNo;
+
+  unixSignalNo = mapPortLibSignalToUnix (portLibrarySignalNo);
+
+  /* do not block any signals */
+  if (sigemptyset (&newAction.sa_mask))
+    {
+      return -1;
+    }
+
+  /* automatically restart system calls that get interrupted by any signal */
+  newAction.sa_flags = SA_RESTART;
+
+  /* setting to SA_SIGINFO will result in "void (*sa_sigaction) (int, siginfo_t *, void *)" to be used, and not "__sighandler_t sa_handler". Both are members of struct sigaction. */
+  /* using the former allows us to access more than just the signal number */
+  newAction.sa_flags |= SA_SIGINFO;
+
+  /*  SA_NODEFER prevents the current signal from being masked in the handler */
+  newAction.sa_flags |= SA_NODEFER;
+
+  /* the master exception handler is... */
+  newAction.sa_sigaction = handler;
+
+  /* now that we've set up the sigaction struct the way we want it, register the handler with the OS */
+  if (HYJSIG_SIGACTION
+      (unixSignalNo, &newAction, &oldActions[unixSignalNo].action))
+    {
+      return -1;
+    }
+  else
+    {
+      oldActions[unixSignalNo].restore = 1;
+    }
+
+  /* we've successfully registered the master handler for this, record it! */
+  signalsWithMasterHandlers |= portLibrarySignalNo;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION mapUnixSignalToPortLib
+
+ /**
+ * The linux signal number is converted to the corresponding port library 
+ * signal number.
+ *
+ * Some signals have subtypes which are detailed in the siginfo_t structure.
+ */
+static U_32
+mapUnixSignalToPortLib (U_32 signalNo, siginfo_t * sigInfo)
+{
+  U_32 index;
+
+  for (index = 0; index < sizeof (signalMap) / sizeof (signalMap[0]); index++)
+    {
+      if (signalMap[index].unixSignalNo == signalNo)
+        {
+
+          if (signalNo == SIGFPE)
+            {
+
+              /* Linux 2.4 kernel bug: 64-bit platforms or in 0.x30000 into si_code */
+              switch (sigInfo->si_code & 0xf)
+                {
+                case FPE_FLTDIV:
+                  return HYPORT_SIG_FLAG_SIGFPE_DIV_BY_ZERO;
+                case FPE_INTDIV:
+                  return HYPORT_SIG_FLAG_SIGFPE_INT_DIV_BY_ZERO;
+                case FPE_INTOVF:
+                  return HYPORT_SIG_FLAG_SIGFPE_INT_OVERFLOW;
+                default:
+                  return HYPORT_SIG_FLAG_SIGFPE;
+                }
+            }
+
+          return signalMap[index].portLibSignalNo;
+        }
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION mapPortLibSignalToUnix
+
+/**
+ * The defined port library signal is converted to the corresponding unix 
+ * signal number.
+ *
+ * Note that FPE signal codes (subtypes) all map to the same signal number and are not included 
+ */
+static U_32
+mapPortLibSignalToUnix (U_32 portLibSignal)
+{
+  U_32 index;
+
+  /* mask out subtypes */
+  portLibSignal &=
+    HYPORT_SIG_FLAG_SIGALLSYNC | HYPORT_SIG_FLAG_SIGQUIT |
+    HYPORT_SIG_FLAG_SIGABRT | HYPORT_SIG_FLAG_SIGTERM;
+
+  for (index = 0; index < sizeof (signalMap) / sizeof (signalMap[0]); index++)
+    {
+
+      if (signalMap[index].portLibSignalNo == portLibSignal)
+        {
+          return signalMap[index].unixSignalNo;
+        }
+
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION registerMasterHandlers
+
+/**
+ * Registers the master handler for the signals in flags that don't have one
+ * yet. We can not handle both synch and asynch signals in one call
+
+ * Calls to this function must be synchronized using syncMonitor
+ *
+ * 
+ * @param[in] flags the flags that we want signals for
+ * @param[in] allowedSubsetOfFlags must be one of
+ * HYPORT_SIG_FLAG_SIGALLSYNC, or HYPORT_SIG_FLAG_SIGALLASYNC
+ * 
+ * 
+ * @return	0 upon success; HYPORT_SIG_ERROR otherwise.
+ *			Possible failure scenarios include attempting to register a handler for
+ *			a signal that is not included in the allowedSubsetOfFlags  
+*/
+static I_32
+registerMasterHandlers (HyPortLibrary * portLibrary, U_32 flags,
+                        U_32 allowedSubsetOfFlags)
+{
+  U_32 flagsSignalsOnly, flagsWithoutHandlers;
+  linux386_sigaction handler;
+
+  if (allowedSubsetOfFlags == HYPORT_SIG_FLAG_SIGALLSYNC)
+    {
+      handler = masterSynchSignalHandler;
+    }
+  else if (allowedSubsetOfFlags == HYPORT_SIG_FLAG_SIGALLASYNC)
+    {
+      handler = masterASynchSignalHandler;
+    }
+  else
+    {
+      return HYPORT_SIG_ERROR;
+    }
+
+  flagsSignalsOnly = flags & allowedSubsetOfFlags;
+  flagsWithoutHandlers = flagsSignalsOnly & (~signalsWithMasterHandlers);
+
+  if (flagsWithoutHandlers)
+    {
+      /* we be registerin' some handlers */
+      U_32 portSignalType = 0;
+
+      /* portSignalType starts off at 4 as it is the smallest synch
+       * signal. In the case that we are registering an asynch
+       * signal, flagsWithoutHandlers already has masked off the
+       * synchronous signals (eg. "4") so we are not at risk of registering a handler
+       * for an incorrect sigal       
+       */
+      for (portSignalType = 4; portSignalType < allowedSubsetOfFlags;
+           portSignalType = portSignalType << 1)
+        {
+          /* iterate through all the  signals and register the master handler for those that don't have one yet */
+
+          if (flagsWithoutHandlers & portSignalType)
+            {
+              /* we need a master handler for this (portSignalType's) signal */
+
+              if (registerSignalHandlerWithOS
+                  (portLibrary, portSignalType, handler))
+                {
+                  return HYPORT_SIG_ERROR;
+                }
+            }
+        }
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION initializeSignalTools
+
+static U_32
+initializeSignalTools (HyPortLibrary * portLibrary)
+{
+
+  /* use this to record the end of the list of signal infos */
+  if (hythread_tls_alloc (&tlsKey))
+    {
+      return -1;
+    }
+
+  /* use this to record the last signal that occured such that we can call jsig_handler in hyexit_shutdown_and_exit */
+  if (hythread_tls_alloc (&tlsKeyCurrentSignal))
+    {
+      return -1;
+    }
+
+  if (hythread_monitor_init_with_name
+      (&masterHandlerMonitor, 0, "portLibrary_hysig_sync_monitor"))
+    {
+      return -1;
+    }
+
+  if (hythread_monitor_init_with_name
+      (&asyncReporterShutdownMonitor, 0,
+       "portLibrary_hysig_asynch_reporter_shutdown_monitor"))
+    {
+      return -1;
+    }
+
+  if (hythread_monitor_init_with_name
+      (&asyncMonitor, 0, "portLibrary_hysig_async_monitor"))
+    {
+      return -1;
+    }
+
+  /* The asynchronous signal reporter will wait on this semaphore  */
+  if (sem_init (&wakeUpASynchReporter, 0, 0))
+    {
+      return -1;
+    }
+
+  /* The asynchronous signal reporter keeps track of the number of pending singals with these... */
+  if (sem_init (&sigQuitPendingSem, 0, 0))
+    {
+      return -1;
+    }
+  if (sem_init (&sigAbrtPendingSem, 0, 0))
+    {
+      return -1;
+    }
+  if (sem_init (&sigTermPendingSem, 0, 0))
+    {
+      return -1;
+    }
+  if (sem_init (&sigReconfigPendingSem, 0, 0))
+    {
+      return -1;
+    }
+
+  if (hythread_create
+      (NULL, 0, HYTHREAD_PRIORITY_MIN, 0, &asynchSignalReporter, NULL))
+    {
+      return -1;
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION destroySignalTools
+
+static U_32
+destroySignalTools (HyPortLibrary * portLibrary)
+{
+  hythread_tls_free (tlsKey);
+  hythread_monitor_destroy (masterHandlerMonitor);
+  hythread_monitor_destroy (asyncReporterShutdownMonitor);
+  hythread_monitor_destroy (asyncMonitor);
+  sem_destroy (&wakeUpASynchReporter);
+  sem_destroy (&sigQuitPendingSem);
+  sem_destroy (&sigAbrtPendingSem);
+  sem_destroy (&sigTermPendingSem);
+  sem_destroy (&sigReconfigPendingSem);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_set_options
+I_32 VMCALL
+hysig_set_options (struct HyPortLibrary * portLibrary, U_32 options)
+{
+
+  if (HYPORT_SIG_OPTIONS_REDUCED_SIGNALS & options)
+    {
+      /* check that we haven't already set any master handlers */
+
+      hythread_monitor_enter (masterHandlerMonitor);
+      if (signalsWithMasterHandlers)
+        {
+          return -1;
+        }
+      hythread_monitor_exit (masterHandlerMonitor);
+
+    }
+
+  signalOptions |= options;
+  return 0;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_get_options
+/* these options should always be 0 */
+U_32 VMCALL
+hysig_get_options (struct HyPortLibrary * portLibrary)
+{
+
+  return signalOptions;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION sig_full_shutdown
+
+static void VMCALL
+sig_full_shutdown (struct HyPortLibrary *portLibrary)
+{
+  hythread_monitor_t globalMonitor = hythread_global_monitor ();
+  U_32 index;
+
+  hythread_monitor_enter (globalMonitor);
+  if (--attachedPortLibraries == 0)
+    {
+
+      /* register the old actions we overwrote with our own */
+      for (index = 0; index < MAX_UNIX_SIGNAL_TYPES; index++)
+        {
+          if (oldActions[index].restore)
+            {
+              HYJSIG_SIGACTION (index, &oldActions[index].action, NULL);
+            }
+        }
+
+      removeAsyncHandlers (portLibrary);
+
+      /* shut down the asynch reporter thread */
+      hythread_monitor_enter (asyncReporterShutdownMonitor);
+      shutDownASynchReporter = 1;
+
+      sem_post (&wakeUpASynchReporter);
+
+      while (shutDownASynchReporter)
+        {
+          hythread_monitor_wait (asyncReporterShutdownMonitor);
+        }
+      hythread_monitor_exit (asyncReporterShutdownMonitor);
+
+      /* destroy all of the remaining monitors */
+      destroySignalTools (portLibrary);
+
+    }                           /* (signalStartupCount) */
+  hythread_monitor_exit (globalMonitor);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION removeAsyncHandlers
+
+static void
+removeAsyncHandlers (HyPortLibrary * portLibrary)
+{
+  /* clean up the list of async handlers */
+  HyLinux386AsyncHandlerRecord *cursor;
+  HyLinux386AsyncHandlerRecord **previousLink;
+
+  hythread_monitor_enter (asyncMonitor);
+
+  /* wait until no signals are being reported */
+  while (asyncThreadCount > 0)
+    {
+      hythread_monitor_wait (asyncMonitor);
+    }
+
+  previousLink = &asyncHandlerList;
+  cursor = asyncHandlerList;
+  while (cursor)
+    {
+      if (cursor->portLib == portLibrary)
+        {
+          *previousLink = cursor->next;
+          portLibrary->mem_free_memory (portLibrary, cursor);
+          cursor = *previousLink;
+        }
+      else
+        {
+          previousLink = &cursor->next;
+          cursor = cursor->next;
+        }
+    }
+
+  hythread_monitor_exit (asyncMonitor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysig_chain_at_shutdown_and_exit
+
+/*  @internal 
+ *
+ * hyexit_shutdown_and_exit needs to call this to ensure the signal is chained to jsig (the application
+ *  handler in the case when the shutdown is due to a fatal signal.
+ * 
+ * @return  
+*/
+void VMCALL
+hysig_chain_at_shutdown_and_exit (struct HyPortLibrary *portLibrary)
+{
+
+  HyCurrentSignal *currentSignal =
+    hythread_tls_get (hythread_self (), tlsKeyCurrentSignal);
+
+  if (currentSignal != NULL)
+    {
+      /* we are shutting down due to a signal, forward it to the application handlers */
+      if (!(signalOptions & HYPORT_SIG_OPTIONS_JSIG_NO_CHAIN))
+        {
+          jsig_handler (currentSignal->signal, currentSignal->sigInfo,
+                        currentSignal->contextInfo);
+        }
+    }
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION
+
+#undef CDEV_CURRENT_FUNCTION

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysl.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysl.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysl.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/port/hysl.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,398 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CDEV_CURRENT_FUNCTION _comment_
+/**
+ * @file
+ * @ingroup Port
+ * @brief shared library
+ */
+
+#undef CDEV_CURRENT_FUNCTION
+
+/* 
+ *	Standard unix shared libraries
+ *	(AIX: 4.2 and higher only)
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+/* Start copy from hyfiletext.c */
+/* __STDC_ISO_10646__ indicates that the platform wchar_t encoding is Unicode */
+/* but older versions of libc fail to set the flag, even though they are Unicode */
+#if defined(__STDC_ISO_10646__) || defined(LINUX)
+#define HYVM_USE_MBTOWC
+#else
+#define HYVM_USE_ICONV
+#include <iconv.h>
+#endif
+
+#if defined(HYVM_USE_MBTOWC) || defined(HYVM_USE_ICONV)
+#include <nl_types.h>
+#include <langinfo.h>
+/* Some older platforms (Netwinder) don't declare CODESET */
+#if !defined(CODESET)
+#define CODESET _NL_CTYPE_CODESET_NAME
+#endif
+#endif
+
+/* End copy */
+
+#include "hyport.h"
+#include "hylib.h"
+#include "portnls.h"
+
+#define PLATFORM_DLL_EXTENSION ".so"
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+#if (defined(HYVM_USE_MBTOWC))
+static void convertWithMBTOWC (struct HyPortLibrary *portLibrary, char *error,
+                               char *errBuf, UDATA bufLen);
+#endif /* HYVM_USE_MBTOWC (autogen) */
+
+#if (defined(HYVM_USE_ICONV))
+static void convertWithIConv (struct HyPortLibrary *portLibrary, char *error,
+                              char *errBuf, UDATA bufLen);
+#endif /* HYVM_USE_ICONV (autogen) */
+
+static void getDLError (struct HyPortLibrary *portLibrary, char *errBuf,
+                        UDATA bufLen);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysl_close_shared_library
+/**
+ * Close a shared library.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] descriptor Shared library handle to close.
+ *
+ * @return 0 on success, any other value on failure.
+ */
+UDATA VMCALL
+hysl_close_shared_library (struct HyPortLibrary *portLibrary,
+                           UDATA descriptor)
+{
+  return (UDATA) dlclose ((void *)descriptor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysl_open_shared_library
+/** 
+ * Opens a shared library .
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] name path Null-terminated string containing the shared library.
+ * @param[out] descriptor Pointer to memory which is filled in with shared-library handle on success.
+ * @param[out] errBuf Buffer to contain an error message on failure.
+ * @param[in] bufLen Size of errBuf.
+ * @param[in] decorate Boolean value indicates whether name should be decorated if it contains path information and cannot be found.
+ *
+ * @return 0 on success, any other value on failure.
+ *
+ * @note contents of descriptor are undefined on failure.
+ */
+UDATA VMCALL
+hysl_open_shared_library (struct HyPortLibrary * portLibrary, char *name,
+                          UDATA * descriptor, BOOLEAN decorate)
+{
+  void *handle;
+  char *openName = name;
+  char mangledName[1024];
+  char errBuf[512];
+
+  if (decorate)
+    {
+      char *p = strrchr (name, '/');
+      if (p)
+        {
+          /* the names specifies a path */
+          portLibrary->str_printf (portLibrary, mangledName, 1024,
+                                   "%.*slib%s" PLATFORM_DLL_EXTENSION,
+                                   (UDATA) p + 1 - (UDATA) name, name, p + 1);
+        }
+      else
+        {
+          portLibrary->str_printf (portLibrary, mangledName, 1024,
+                                   "lib%s" PLATFORM_DLL_EXTENSION, name);
+        }
+      openName = mangledName;
+    }
+
+  handle = dlopen (openName, RTLD_NOW);
+  if (handle == NULL)
+    {
+      getDLError (portLibrary, errBuf, sizeof (errBuf));
+      if (portLibrary->file_attr (portLibrary, openName) == HyIsFile)
+        {
+          return portLibrary->error_set_last_error_with_message (portLibrary,
+                                                                 HYPORT_SL_INVALID,
+                                                                 errBuf);
+        }
+      else
+        {
+          return portLibrary->error_set_last_error_with_message (portLibrary,
+                                                                 HYPORT_SL_NOT_FOUND,
+                                                                 errBuf);
+        }
+    }
+
+  *descriptor = (UDATA) handle;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysl_lookup_name
+/**
+ * Search for a function named 'name' taking argCount in the shared library 'descriptor'.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] descriptor Shared library to search.
+ * @param[in] name Function to look up.
+ * @param[out] func Pointer to the function.
+ * @param[in] argSignature Argument signature.
+ *
+ * @return 0 on success, any other value on failure.
+ *
+ * argSignature is a C (ie: NUL-terminated) string with the following possible values for each character:
+ *
+ *		V	- void
+ *		Z	- boolean
+ *		B	- byte
+ *		C	- char (16 bits)
+ *		I	- integer (32 bits)
+ *		J	- long (64 bits)
+ *		F	- float (32 bits) 
+ *		D	- double (64 bits) 
+ *		L	- object / pointer (32 or 64, depending on platform)
+ *		P	- pointer-width platform data. (in this context an IDATA)
+ *
+ * Lower case signature characters imply unsigned value.
+ * Upper case signature characters imply signed values.
+ * If it doesn't make sense to be signed/unsigned (eg: V, L, F, D Z) the character is upper case.
+ * 
+ * argList[0] is the return type from the function.
+ * The argument list is as it appears in english: list is left (1) to right (argCount)
+ *
+ * @note contents of func are undefined on failure.
+ */
+UDATA VMCALL
+hysl_lookup_name (struct HyPortLibrary * portLibrary, UDATA descriptor,
+                  char *name, UDATA * func, const char *argSignature)
+{
+  void *address;
+  address = dlsym ((void *)descriptor, name);
+  if (address == NULL)
+    {
+      return 1;
+    }
+  *func = (UDATA) address;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION getDLError
+static void
+getDLError (struct HyPortLibrary *portLibrary, char *errBuf, UDATA bufLen)
+{
+  char *error;
+
+  if (bufLen == 0)
+    {
+      return;
+    }
+
+  error = dlerror ();
+  if (error == NULL || error[0] == '\0')
+    {
+      /* just in case another thread consumed our error message */
+      error = (char *)portLibrary->nls_lookup_message (portLibrary,
+                                               HYNLS_ERROR |
+                                               HYNLS_DO_NOT_APPEND_NEWLINE,
+                                               HYNLS_PORT_SL_UNKOWN_ERROR,
+                                               "Unknown error");
+      strncpy (errBuf, error, bufLen);
+      errBuf[bufLen - 1] = '\0';
+      return;
+    }
+
+#if defined(HYVM_USE_MBTOWC)
+  convertWithMBTOWC (portLibrary, error, errBuf, bufLen);
+#elif defined(HYVM_USE_ICONV)
+  convertWithIConv (portLibrary, error, errBuf, bufLen);
+#else
+  strncpy (errBuf, error, bufLen);
+  errBuf[bufLen - 1] = '\0';
+#endif
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION convertWithIConv
+#if (defined(HYVM_USE_ICONV))
+static void
+convertWithIConv (struct HyPortLibrary *portLibrary, char *error,
+                  char *errBuf, UDATA bufLen)
+{
+  iconv_t converter;
+  size_t inbytesleft, outbytesleft;
+  char *inbuf, *outbuf;
+  converter = iconv_open ("UTF-8", nl_langinfo (CODESET));
+  if (converter == (iconv_t) - 1)
+    {
+      /* no converter available for this code set. Just dump the platform chars */
+      strncpy (errBuf, error, bufLen);
+      errBuf[bufLen - 1] = '\0';
+      return;
+    }
+  inbuf = (char *) error;       /* for some reason this argument isn't const */
+  outbuf = errBuf;
+  inbytesleft = strlen (error);
+  outbytesleft = bufLen - 1;
+  while ((outbytesleft > 0) && (inbytesleft > 0))
+    {
+      if ((size_t) - 1 ==
+          iconv (converter, &inbuf, &inbytesleft, &outbuf, &outbytesleft))
+        {
+          if (errno == E2BIG)
+            {
+              break;
+            }
+          /* if we couldn't translate this character, copy one byte verbatim */
+          *outbuf = *inbuf;
+          outbuf++;
+          inbuf++;
+          inbytesleft--;
+          outbytesleft--;
+        }
+    }
+  *outbuf = '\0';
+  iconv_close (converter);
+}
+#endif /* HYVM_USE_ICONV (autogen) */
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION convertWithMBTOWC
+#if (defined(HYVM_USE_MBTOWC))
+static void
+convertWithMBTOWC (struct HyPortLibrary *portLibrary, char *error,
+                   char *errBuf, UDATA bufLen)
+{
+  char *out, *end, *walk;
+  wchar_t ch;
+  int ret;
+  out = errBuf;
+  end = &errBuf[bufLen - 1];
+  walk = error;
+  /* reset the shift state */
+  mbtowc (NULL, NULL, 0);
+  while (*walk)
+    {
+      ret = mbtowc (&ch, walk, MB_CUR_MAX);
+      if (ret < 0)
+        {
+          ch = *walk++;
+        }
+      else if (ret == 0)
+        {
+          break;
+        }
+      else
+        {
+          walk += ret;
+        }
+      if (ch == '\r')
+        continue;
+      if (ch == '\n')
+        ch = ' ';
+      if (ch < 0x80)
+        {
+          if ((out + 1) > end)
+            break;
+          *out++ = (char) ch;
+        }
+      else if (ch < 0x800)
+        {
+          if ((out + 2) > end)
+            break;
+          *out++ = (char) (0xc0 | ((ch >> 6) & 0x1f));
+          *out++ = (char) (0x80 | (ch & 0x3f));
+        }
+      else
+        {
+          if ((out + 3) > end)
+            break;
+          *out++ = (char) (0xe0 | ((ch >> 12) & 0x0f));
+          *out++ = (char) (0x80 | ((ch >> 6) & 0x3f));
+          *out++ = (char) (0x80 | (ch & 0x3f));
+        }
+    }
+  *out = '\0';
+}
+#endif /* HYVM_USE_MBTOWC (autogen) */
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysl_shutdown
+/**
+ * PortLibrary shutdown.
+ *
+ * This function is called during shutdown of the portLibrary.  Any resources that were created by @ref hysl_startup
+ * should be destroyed here.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @note Most implementations will be empty.
+ */
+void VMCALL
+hysl_shutdown (struct HyPortLibrary *portLibrary)
+{
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysl_startup
+/**
+ * PortLibrary startup.
+ *
+ * This function is called during startup of the portLibrary.  Any resources that are required for
+ * the shared library operations may be created here.  All resources created here should be destroyed
+ * in @ref hysl_shutdown.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @return 0 on success, negative error code on failure.  Error code values returned are
+ * \arg HYPORT_ERROR_STARTUP_SL
+ *
+ * @note Most implementations will simply return success.
+ */
+I_32 VMCALL
+hysl_startup (struct HyPortLibrary *portLibrary)
+{
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION
+
+#undef CDEV_CURRENT_FUNCTION