Forum

Need a review on some old code

Discuss programming topics for any language, any source base. If it is programming related but doesn't fit in one of the below categories, it goes here.

Moderator: InsideQC Admins

Need a review on some old code

Postby revelator » Fri Jun 05, 2015 10:40 am

This code piece is what allows gcc to throw exceptions from statically linked runtime builds.
It's rather old as it was first used in gcc-3.2 from the mingw project because the old gcc could not be built with shared runtimes at that time, so it was needed.
Nowadays both me and TDM use it to allow linking statically to the gcc and libstdc++ runtimes to avoid having to rely on 2 or more of gcc's runtime dll's.
Problem is that it causes the 32 bit gcc to sometimes go bonkers because the pointers it throws are all assumed to be 8 bytes (which they only are on 64 bit gcc) so i changed it a bit.

Code: Select all
/* -- shmem-win32.c --
 *
 * See gcc/shmem.h for a description of __SHMEM.
 *
 * This is the win32 implementation of __SHMEM, based in part on a mechanism
 * originally developed by Thomas Pfaff and Adriano dos Santos Fernandes,
 * reimplemented by JohnE as of 2010.
 *
 * This code is released into the public domain without warranty; it may be
 * freely used and redistributed.
 */

#include "shmem.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <malloc.h>

static const char *shmem_version_prefix = "gcc-shmem";

static void __w32sp_trap(void)
{
   DebugBreak();
}

static void *get_ptr_from_atom(ATOM atom, char *name_buf, intptr_t name_buf_len, intptr_t ptr_offset)
{
   size_t   ptr = 0;
   intptr_t   i, ptr_len = sizeof(void *) * sizeof(intptr_t); /* because int is newer 8 bytes, long is, so use intptr_t to make sure its big enough, original allways assumed 8 bytes but it might be 4 on 32 bit gcc  */

   if ((name_buf_len - ptr_offset - 1) < ptr_len)
   {
      __w32sp_trap();
   }

   if (!GetAtomNameA(atom, name_buf, name_buf_len))
   {
      __w32sp_trap();
   }

   for (i = 0; i < ptr_len; ++i)
   {
      if (name_buf[ptr_offset + i] == 'A')
      {
         ptr |= (1 << (ptr_len - i));
      }
   }
   return (void *)ptr;
}

void *__shmem_grab(const char *name, intptr_t size, void (*initfunc)(void *))
{
   intptr_t   prefix_len = strlen(shmem_version_prefix);
   intptr_t   name_len = strlen(name);
   intptr_t   i, ptr_len = sizeof(void *) * sizeof(intptr_t); /* because int is newer 8 bytes, long is, so use intptr_t to make sure its big enough, original allways assumed 8 bytes but it might be 4 on 32 bit gcc   */
   char      full_atom_name[prefix_len + 1 + name_len + 1 + ptr_len + 2];
   HANDLE      hmutex;
   ATOM      atom;
   void      *ret = 0;
   void      *shared_mem;

   memcpy(full_atom_name, shmem_version_prefix, prefix_len);
   full_atom_name[prefix_len] = '-';
   memcpy(full_atom_name + prefix_len + 1, name, name_len);
   memset(full_atom_name + prefix_len + 1 + name_len + 1, 'a', ptr_len);
   full_atom_name[prefix_len + 1 + name_len + 1 + ptr_len] = 0;
   full_atom_name[prefix_len + 1 + name_len] = 0;
   hmutex = CreateMutexA(0, FALSE, full_atom_name);
   full_atom_name[prefix_len + 1 + name_len] = '-';

   if (WaitForSingleObject(hmutex, INFINITE) != WAIT_OBJECT_0)
   {
      __w32sp_trap();
   }
   atom = FindAtomA(full_atom_name);

   if (atom)
   {
      ret = get_ptr_from_atom(atom, full_atom_name, prefix_len + 1 + name_len + 1 + ptr_len + 1, prefix_len + 1 + name_len + 1);
   }
   else
   {
      shared_mem = malloc(size);

      for (i = 0; i < ptr_len; ++i)
      {
         if ((((size_t)shared_mem) >> (ptr_len - i)) & 1)
         {
            full_atom_name[prefix_len + 1 + name_len + 1 + i] = 'A';
         }
      }
      atom = AddAtomA(full_atom_name);

      if (!atom)
      {
         __w32sp_trap();
      }
      ret = get_ptr_from_atom(atom, full_atom_name, prefix_len + 1 + name_len + 1 + ptr_len + 1, prefix_len + 1 + name_len + 1);

      if (ret == shared_mem)
      {
         memset(ret, 0, size);

         if (initfunc)
         {
            initfunc(ret);
         }
      }
      else
      {
         free(shared_mem);
      }
   }
   ReleaseMutex(hmutex);
   CloseHandle(hmutex);

   return ret;
}


as you can see its a rather simple codepiece :) but hang on heres the header.

Code: Select all
/* -- shmem.h --
 *
 * The __SHMEM mechanism is for sharing named pointers among the instances of a
 * static library compiled into separate modules (binaries or shared libraries)
 * in one runtime program. It's used in libgcc and libstdc++ to be able to
 * propagate exceptions out of shared libraries even which libgcc and libstdc++
 * are compiled in statically.
 *
 * This code is released into the public domain without warranty; it may be
 * freely used and redistributed.
 */

/* for intptr_t */
#include <stdint.h>

#if defined(_WIN32) || defined(_WIN64)
#define HAVE_SHMEM_IMPL
#endif

#if defined(HAVE_SHMEM_IMPL) && !defined(SHARED)

#ifdef __cplusplus
#define __SHMEM_CLINK extern "C"
#else
#define __SHMEM_CLINK
#endif

__SHMEM_CLINK void *__shmem_grab(const char *name, intptr_t size, void (*initfunc)(void *));

#define __SHMEM_CONCAT2(a, b) __CONCAT2_INDIR(a, b)
#define __CONCAT2_INDIR(a, b) a ## b

#define __SHMEM_DEFINE(type, name) \
 type* __SHMEM_CONCAT2(__shmem_ptr_, name) = 0; \
 type* __SHMEM_CONCAT2(__shmem_grabber_, name)() \
 { \
   return (type *)__shmem_grab(# name, sizeof(type), 0); \
 }

#define __SHMEM_DEFINE_INIT(type, name, initval) \
 type* __SHMEM_CONCAT2(__shmem_ptr_, name) = 0; \
 __SHMEM_CLINK void __SHMEM_CONCAT2(__shmem_init_, name)(void *mem) \
 { \
   type temp = initval; \
   *((type*)mem) = temp; \
 } \
 type* __SHMEM_CONCAT2(__shmem_grabber_, name)() \
 { \
   return (type *)__shmem_grab(# name, sizeof(type), __SHMEM_CONCAT2(__shmem_init_, name)); \
 }

#define __SHMEM_DEFINE_ARRAY(type, name, size) \
 type* __SHMEM_CONCAT2(__shmem_ptr_, name) = 0; \
 type* __SHMEM_CONCAT2(__shmem_grabber_, name)() \
 { \
   return (type *)__shmem_grab(# name, sizeof(type) * size, 0); \
 }

#define __SHMEM_DECLARE(type, name) \
 extern type* __SHMEM_CONCAT2(__shmem_ptr_, name); \
 type* __SHMEM_CONCAT2(__shmem_grabber_, name)();

#define __SHMEM_GET(name) \
 (*( \
 (__SHMEM_CONCAT2(__shmem_ptr_, name)) \
 ? \
 (__SHMEM_CONCAT2(__shmem_ptr_, name)) \
 : \
 ((__SHMEM_CONCAT2(__shmem_ptr_, name)) = __SHMEM_CONCAT2(__shmem_grabber_, name)()) \
 ))

#define __SHMEM_GET_ARRAY(name) \
 ( \
 (__SHMEM_CONCAT2(__shmem_ptr_, name)) \
 ? \
 (__SHMEM_CONCAT2(__shmem_ptr_, name)) \
 : \
 ((__SHMEM_CONCAT2(__shmem_ptr_, name)) = __SHMEM_CONCAT2(__shmem_grabber_, name)()) \
 )

#else

#define __SHMEM_DEFINE(type, name) type name;
#define __SHMEM_DEFINE_INIT(type, name, initval) type name = initval;
#define __SHMEM_DEFINE_ARRAY(type, name, size) type name[size];
#define __SHMEM_DECLARE(type, name) extern type name;
#define __SHMEM_GET(name) name
#define __SHMEM_GET_ARRAY(name) name

#endif


If anyone could go through it and maybe point out mistakes i would be gratefull.
Productivity is a state of mind.
User avatar
revelator
 
Posts: 2531
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Return to General Programming

Who is online

Users browsing this forum: No registered users and 1 guest