/* LIBPIKA - The PIKA Library * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball * * pika-shm.c * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include "config.h" #include #if defined(USE_SYSV_SHM) #ifdef HAVE_IPC_H #include #endif #ifdef HAVE_SHM_H #include #endif #elif defined(USE_POSIX_SHM) #ifdef HAVE_UNISTD_H #include #endif #include #include #endif /* USE_POSIX_SHM */ #include #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN) # ifdef STRICT # undef STRICT # endif # define STRICT # ifdef _WIN32_WINNT # undef _WIN32_WINNT # endif # define _WIN32_WINNT 0x0601 # include # include # undef RGB # define USE_WIN32_SHM 1 #endif #include "pika.h" #include "pika-shm.h" #define TILE_MAP_SIZE (pika_tile_width () * pika_tile_height () * 32) #define ERRMSG_SHM_FAILED "Could not attach to pika shared memory segment" #ifdef USE_WIN32_SHM static HANDLE _shm_handle; #endif static gint _shm_ID = -1; static guchar *_shm_addr = NULL; guchar * _pika_shm_addr (void) { return _shm_addr; } void _pika_shm_open (gint shm_ID) { _shm_ID = shm_ID; if (_shm_ID != -1) { #if defined(USE_SYSV_SHM) /* Use SysV shared memory mechanisms for transferring tile data. */ _shm_addr = (guchar *) shmat (_shm_ID, NULL, 0); if (_shm_addr == (guchar *) -1) { g_error ("shmat() failed: %s\n" ERRMSG_SHM_FAILED, g_strerror (errno)); } #elif defined(USE_WIN32_SHM) /* Use Win32 shared memory mechanisms for transferring tile data. */ gchar fileMapName[128]; wchar_t *w_fileMapName; /* From the id, derive the file map name */ g_snprintf (fileMapName, sizeof (fileMapName), "PIKA%d.SHM", _shm_ID); w_fileMapName = g_utf8_to_utf16 (fileMapName, -1, NULL, NULL, NULL); if (!w_fileMapName) g_error ("Cannot convert to UTF16"); /* Open the file mapping */ _shm_handle = OpenFileMappingW (FILE_MAP_ALL_ACCESS, 0, w_fileMapName); g_clear_pointer (&w_fileMapName, g_free); if (_shm_handle) { /* Map the shared memory into our address space for use */ _shm_addr = (guchar *) MapViewOfFile (_shm_handle, FILE_MAP_ALL_ACCESS, 0, 0, TILE_MAP_SIZE); /* Verify that we mapped our view */ if (!_shm_addr) { g_error ("MapViewOfFile error: %lu... " ERRMSG_SHM_FAILED, GetLastError ()); } } else { g_error ("OpenFileMapping error: %lu... " ERRMSG_SHM_FAILED, GetLastError ()); } #elif defined(USE_POSIX_SHM) /* Use POSIX shared memory mechanisms for transferring tile data. */ gchar map_file[32]; gint shm_fd; /* From the id, derive the file map name */ g_snprintf (map_file, sizeof (map_file), "/pika-shm-%d", _shm_ID); /* Open the file mapping */ shm_fd = shm_open (map_file, O_RDWR, 0600); if (shm_fd != -1) { /* Map the shared memory into our address space for use */ _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_addr == MAP_FAILED) { g_error ("mmap() failed: %s\n" ERRMSG_SHM_FAILED, g_strerror (errno)); } close (shm_fd); } else { g_error ("shm_open() failed: %s\n" ERRMSG_SHM_FAILED, g_strerror (errno)); } #endif } } void _pika_shm_close (void) { #if defined(USE_SYSV_SHM) if ((_shm_ID != -1) && _shm_addr) shmdt ((char *) _shm_addr); #elif defined(USE_WIN32_SHM) if (_shm_handle) CloseHandle (_shm_handle); #elif defined(USE_POSIX_SHM) if ((_shm_ID != -1) && (_shm_addr != MAP_FAILED)) munmap (_shm_addr, TILE_MAP_SIZE); #endif }