gimppluginshm.c 6.93 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
Elliot Lee's avatar
Elliot Lee committed
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4 5
 * gimppluginhsm.c
 *
6
 * This program is free software: you can redistribute it and/or modify
Elliot Lee's avatar
Elliot Lee committed
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
Elliot Lee's avatar
Elliot Lee committed
9 10 11 12 13 14 15 16
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19

Elliot Lee's avatar
Elliot Lee committed
20
#include "config.h"
21

22 23
#include <sys/types.h>

24 25 26 27
#include <errno.h>

#if defined(USE_SYSV_SHM)

28 29
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
Manish Singh's avatar
Manish Singh committed
30 31
#endif

32 33
#ifdef HAVE_SHM_H
#include <sys/shm.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
34
#endif
35

36 37 38 39 40 41 42 43 44 45 46
#elif defined(USE_POSIX_SHM)

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <fcntl.h>
#include <sys/mman.h>

#endif /* USE_POSIX_SHM */

47
#include <gio/gio.h>
48
#include <gegl.h>
49

50
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
51

52 53 54 55
#define STRICT
#include <windows.h>
#include <process.h>

56
#ifdef G_OS_WIN32
57 58 59 60
#include <fcntl.h>
#include <io.h>
#endif

61 62
#define USE_WIN32_SHM 1

63
#endif /* G_OS_WIN32 || G_WITH_CYGWIN */
64

65
#include "plug-in-types.h"
66

67 68
#include "core/gimp-utils.h"

69
#include "gimppluginshm.h"
70

71 72
#include "gimp-log.h"

73

74
#define TILE_MAP_SIZE (GIMP_PLUG_IN_TILE_WIDTH * GIMP_PLUG_IN_TILE_HEIGHT * 32)
Michael Natterer's avatar
Michael Natterer committed
75 76 77 78

#define ERRMSG_SHM_DISABLE "Disabling shared memory tile transport"


79
struct _GimpPlugInShm
80 81 82
{
  gint    shm_ID;
  guchar *shm_addr;
Elliot Lee's avatar
Elliot Lee committed
83

84
#if defined(USE_WIN32_SHM)
85
  HANDLE  shm_handle;
86
#endif
87
};
88

89

90 91
GimpPlugInShm *
gimp_plug_in_shm_new (void)
92 93 94 95 96
{
  /* allocate a piece of shared memory for use in transporting tiles
   *  to plug-ins. if we can't allocate a piece of shared memory then
   *  we'll fall back on sending the data over the pipe.
   */
97

98
  GimpPlugInShm *shm = g_slice_new0 (GimpPlugInShm);
99 100

  shm->shm_ID = -1;
101

Michael Natterer's avatar
Michael Natterer committed
102
#if defined(USE_SYSV_SHM)
103

Michael Natterer's avatar
Michael Natterer committed
104 105 106
  /* Use SysV shared memory mechanisms for transferring tile data. */
  {
    shm->shm_ID = shmget (IPC_PRIVATE, TILE_MAP_SIZE, IPC_CREAT | 0600);
107

Michael Natterer's avatar
Michael Natterer committed
108 109 110 111 112 113 114 115 116 117 118
    if (shm->shm_ID != -1)
      {
        shm->shm_addr = (guchar *) shmat (shm->shm_ID, NULL, 0);

        if (shm->shm_addr == (guchar *) -1)
          {
            g_printerr ("shmat() failed: %s\n" ERRMSG_SHM_DISABLE,
                        g_strerror (errno));
            shmctl (shm->shm_ID, IPC_RMID, NULL);
            shm->shm_ID = -1;
          }
119 120

#ifdef IPC_RMID_DEFERRED_RELEASE
Michael Natterer's avatar
Michael Natterer committed
121 122
        if (shm->shm_addr != (guchar *) -1)
          shmctl (shm->shm_ID, IPC_RMID, NULL);
123
#endif
Michael Natterer's avatar
Michael Natterer committed
124 125 126 127 128 129 130
      }
    else
      {
        g_printerr ("shmget() failed: %s\n" ERRMSG_SHM_DISABLE,
                    g_strerror (errno));
      }
  }
131

132 133 134
#elif defined(USE_WIN32_SHM)

  /* Use Win32 shared memory mechanisms for transferring tile data. */
Michael Natterer's avatar
Michael Natterer committed
135 136 137 138 139 140 141 142 143 144 145
  {
    gint  pid;
    gchar fileMapName[MAX_PATH];

    /* Our shared memory id will be our process ID */
    pid = GetCurrentProcessId ();

    /* From the id, derive the file map name */
    g_snprintf (fileMapName, sizeof (fileMapName), "GIMP%d.SHM", pid);

    /* Create the file mapping into paging space */
146
    shm->shm_handle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL,
Michael Natterer's avatar
Michael Natterer committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
                                         PAGE_READWRITE, 0,
                                         TILE_MAP_SIZE,
                                         fileMapName);

    if (shm->shm_handle)
      {
        /* Map the shared memory into our address space for use */
        shm->shm_addr = (guchar *) MapViewOfFile (shm->shm_handle,
                                                  FILE_MAP_ALL_ACCESS,
                                                  0, 0, TILE_MAP_SIZE);

        /* Verify that we mapped our view */
        if (shm->shm_addr)
          {
            shm->shm_ID = pid;
          }
        else
          {
            g_printerr ("MapViewOfFile error: %d... " ERRMSG_SHM_DISABLE,
                        GetLastError ());
          }
      }
    else
      {
        g_printerr ("CreateFileMapping error: %d... " ERRMSG_SHM_DISABLE,
                    GetLastError ());
      }
  }
175

176 177 178
#elif defined(USE_POSIX_SHM)

  /* Use POSIX shared memory mechanisms for transferring tile data. */
Michael Natterer's avatar
Michael Natterer committed
179 180 181 182 183 184
  {
    gint  pid;
    gchar shm_handle[32];
    gint  shm_fd;

    /* Our shared memory id will be our process ID */
185
    pid = gimp_get_pid ();
Michael Natterer's avatar
Michael Natterer committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

    /* From the id, derive the file map name */
    g_snprintf (shm_handle, sizeof (shm_handle), "/gimp-shm-%d", pid);

    /* Create the file mapping into paging space */
    shm_fd = shm_open (shm_handle, O_RDWR | O_CREAT, 0600);

    if (shm_fd != -1)
      {
        if (ftruncate (shm_fd, TILE_MAP_SIZE) != -1)
          {
            /* Map the shared memory into our address space for use */
            shm->shm_addr = (guchar *) mmap (NULL, TILE_MAP_SIZE,
                                             PROT_READ | PROT_WRITE, MAP_SHARED,
                                             shm_fd, 0);

            /* Verify that we mapped our view */
            if (shm->shm_addr != MAP_FAILED)
              {
                shm->shm_ID = pid;
              }
            else
              {
                g_printerr ("mmap() failed: %s\n" ERRMSG_SHM_DISABLE,
                            g_strerror (errno));

                shm_unlink (shm_handle);
              }
          }
        else
          {
            g_printerr ("ftruncate() failed: %s\n" ERRMSG_SHM_DISABLE,
                        g_strerror (errno));

            shm_unlink (shm_handle);
          }

        close (shm_fd);
      }
    else
      {
        g_printerr ("shm_open() failed: %s\n" ERRMSG_SHM_DISABLE,
                    g_strerror (errno));
      }
  }
231

Michael Natterer's avatar
Michael Natterer committed
232
#endif
233

Michael Natterer's avatar
Michael Natterer committed
234
  if (shm->shm_ID == -1)
235
    {
236
      g_slice_free (GimpPlugInShm, shm);
Michael Natterer's avatar
Michael Natterer committed
237
      shm = NULL;
238
    }
239 240 241 242
  else
    {
      GIMP_LOG (SHM, "attached shared memory segment ID = %d", shm->shm_ID);
    }
243

244
  return shm;
245 246
}

Elliot Lee's avatar
Elliot Lee committed
247
void
248
gimp_plug_in_shm_free (GimpPlugInShm *shm)
Elliot Lee's avatar
Elliot Lee committed
249
{
250
  g_return_if_fail (shm != NULL);
251

Michael Natterer's avatar
Michael Natterer committed
252 253 254
  if (shm->shm_ID != -1)
    {

255
#if defined (USE_SYSV_SHM)
256

257
      shmdt (shm->shm_addr);
258 259

#ifndef IPC_RMID_DEFERRED_RELEASE
260
      shmctl (shm->shm_ID, IPC_RMID, NULL);
261
#endif
Elliot Lee's avatar
Elliot Lee committed
262

263 264
#elif defined(USE_WIN32_SHM)

Michael Natterer's avatar
Michael Natterer committed
265 266
      if (shm->shm_handle)
        CloseHandle (shm->shm_handle);
267 268 269 270 271

#elif defined(USE_POSIX_SHM)

      gchar shm_handle[32];

272
      munmap (shm->shm_addr, TILE_MAP_SIZE);
273 274

      g_snprintf (shm_handle, sizeof (shm_handle), "/gimp-shm-%d",
275
                  shm->shm_ID);
276 277 278 279

      shm_unlink (shm_handle);

#endif
280

281
      GIMP_LOG (SHM, "detached shared memory segment ID = %d", shm->shm_ID);
Michael Natterer's avatar
Michael Natterer committed
282 283
    }

284
  g_slice_free (GimpPlugInShm, shm);
Elliot Lee's avatar
Elliot Lee committed
285 286
}

287
gint
288
gimp_plug_in_shm_get_ID (GimpPlugInShm *shm)
Elliot Lee's avatar
Elliot Lee committed
289
{
290
  g_return_val_if_fail (shm != NULL, -1);
291

292
  return shm->shm_ID;
Elliot Lee's avatar
Elliot Lee committed
293 294
}

295
guchar *
296
gimp_plug_in_shm_get_addr (GimpPlugInShm *shm)
Elliot Lee's avatar
Elliot Lee committed
297
{
298
  g_return_val_if_fail (shm != NULL, NULL);
299

300
  return shm->shm_addr;
Elliot Lee's avatar
Elliot Lee committed
301
}