SphinxBase  0.6
src/libsphinxbase/util/mmio.c
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
00002 /* ====================================================================
00003  * Copyright (c) 2005 Carnegie Mellon University.  All rights 
00004  * reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer. 
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in
00015  *    the documentation and/or other materials provided with the
00016  *    distribution.
00017  *
00018  * This work was supported in part by funding from the Defense Advanced 
00019  * Research Projects Agency and the National Science Foundation of the 
00020  * United States of America, and the CMU Sphinx Speech Consortium.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 
00023  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
00024  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00025  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
00026  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00028  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00029  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00030  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00031  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00032  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * ====================================================================
00035  *
00036  */
00037 /*********************************************************************
00038  *
00039  * File: mmio.c
00040  * 
00041  * Description: mmap() wrappers for Unix/Windows
00042  * 
00043  * Author: David Huggins-Daines <dhuggins@cs.cmu.edu>
00044  * 
00045  *********************************************************************/
00046 
00047 #include <string.h>
00048 #include <stdlib.h>
00049 
00050 #ifdef GNUWINCE
00051 # include <sys/wcebase.h>
00052 # include <sys/wcetypes.h>
00053 # include <sys/wcememory.h>
00054 # include <sys/wcefile.h>
00055 #elif defined(__SYMBIAN32__) /* SYMBIAN32 must be before WIN32 since Symbian SDK defines WIN32 as well */
00056 # include <unistd.h>
00057 # include <fcntl.h>
00058 # include <sys/stat.h>
00059 # include <sys/mman.h>
00060 #elif defined(_WIN32)
00061 # include <windows.h>
00062 #else
00063 # include <unistd.h>
00064 # include <fcntl.h>
00065 # include <sys/stat.h>
00066 # include <sys/file.h>
00067 # include <sys/mman.h>
00068 #endif
00069 
00070 #include "sphinxbase/prim_type.h"
00071 #include "sphinxbase/err.h"
00072 #include "sphinxbase/mmio.h"
00073 #include "sphinxbase/ckd_alloc.h"
00074 
00076 #if defined(_WIN32_WCE) || defined(GNUWINCE)
00077 struct mmio_file_s {
00078         int dummy;
00079 };
00080 
00081 mmio_file_t *
00082 mmio_file_read(const char *filename)
00083 {
00084     HANDLE ffm, fd;
00085     WCHAR *wfilename;
00086     void *rv;
00087     int len;
00088 
00089     len = mbstowcs(NULL, filename, 0) + 1;
00090     wfilename = malloc(len * sizeof(WCHAR));
00091     mbstowcs(wfilename, filename, len);
00092 
00093     if ((ffm =
00094          CreateFileForMappingW(wfilename, GENERIC_READ, FILE_SHARE_READ,
00095                                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
00096                                NULL)) == INVALID_HANDLE_VALUE) {
00097         E_ERROR("Failed to CreateFileForMapping(%s): %08x\n", filename,
00098                 GetLastError());
00099         return NULL;
00100     }
00101     if ((fd =
00102          CreateFileMappingW(ffm, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) {
00103         E_ERROR("Failed to CreateFileMapping: %08x\n", GetLastError());
00104         CloseHandle(ffm);
00105         return NULL;
00106     }
00107     rv = MapViewOfFile(fd, FILE_MAP_READ, 0, 0, 0);
00108     free(wfilename);
00109     CloseHandle(ffm);
00110     CloseHandle(fd);
00111 
00112     return (mmio_file_t *) rv;
00113 }
00114 
00115 void
00116 mmio_file_unmap(mmio_file_t *mf)
00117 {
00118     if (!UnmapViewOfFile((void *)mf)) {
00119         E_ERROR("Failed to UnmapViewOfFile: %08x\n", GetLastError());
00120     }
00121 }
00122 
00123 void *
00124 mmio_file_ptr(mmio_file_t *mf)
00125 {
00126     return (void *)mf;
00127 }
00128 
00129 #elif defined(WIN32) /* !WINCE */
00130 struct mmio_file_s {
00131         int dummy;
00132 };
00133 
00134 mmio_file_t *
00135 mmio_file_read(const char *filename)
00136 {
00137     HANDLE ffm, fd;
00138     void *rv;
00139 
00140     if ((ffm = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
00141                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
00142                          NULL)) == INVALID_HANDLE_VALUE) {
00143         E_ERROR("Failed to CreateFile(%s): %08x\n",
00144                 filename, GetLastError());
00145         return NULL;
00146     }
00147     if ((fd = CreateFileMapping(ffm, NULL,
00148                                 PAGE_READONLY, 0, 0, NULL)) == NULL) {
00149         E_ERROR("Failed to CreateFileMapping: %08x\n", GetLastError());
00150         CloseHandle(ffm);
00151     }
00152     rv = MapViewOfFile(fd, FILE_MAP_READ, 0, 0, 0);
00153     CloseHandle(ffm);
00154     CloseHandle(fd);
00155 
00156     return (mmio_file_t *)rv;
00157 }
00158 
00159 void
00160 mmio_file_unmap(mmio_file_t *mf)
00161 {
00162     if (!UnmapViewOfFile((void *)mf)) {
00163         E_ERROR("Failed to UnmapViewOfFile: %08x\n", GetLastError());
00164     }
00165 }
00166 
00167 void *
00168 mmio_file_ptr(mmio_file_t *mf)
00169 {
00170     return (void *)mf;
00171 }
00172 
00173 #else /* !WIN32, !WINCE */
00174 #if defined(__ADSPBLACKFIN__) /* This is true for both uClinux and VisualDSP++,
00175                                  but actually we need a better way to detect it. */
00176 struct mmio_file_s {
00177     int dummy;
00178 };
00179 
00180 mmio_file_t *
00181 mmio_file_read(const char *filename)
00182 {
00183         E_FATAL("mmio is not implemented on this platform!");
00184     return NULL;
00185 }
00186 
00187 void
00188 mmio_file_unmap(mmio_file_t *mf)
00189 {
00190         E_FATAL("mmio is not implemented on this platform!");
00191 }
00192 
00193 void *
00194 mmio_file_ptr(mmio_file_t *mf)
00195 {
00196         E_FATAL("mmio is not implemented on this platform!");
00197     return NULL;
00198 }
00199 #else /* !__ADSPBLACKFIN__ */
00200 struct mmio_file_s {
00201     void *ptr;
00202     size_t mapsize;
00203 };
00204 
00205 mmio_file_t *
00206 mmio_file_read(const char *filename)
00207 {
00208     mmio_file_t *mf;
00209     struct stat buf;
00210     void *ptr;
00211     int fd;
00212     size_t pagesize;
00213 
00214     if ((fd = open(filename, O_RDONLY)) == -1) {
00215         E_ERROR_SYSTEM("Failed to open %s", filename);
00216         return NULL;
00217     }
00218     if (fstat(fd, &buf) == -1) {
00219         E_ERROR_SYSTEM("Failed to stat %s", filename);
00220         return NULL;
00221     }
00222     ptr = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
00223     if (ptr == (void *)-1) {
00224         E_ERROR_SYSTEM("Failed to mmap %lld bytes", (unsigned long long)buf.st_size);
00225         return NULL;
00226     }
00227     close(fd);
00228     mf = ckd_calloc(1, sizeof(*mf));
00229     mf->ptr = ptr;
00230     /* Align map size to next page. */
00231     pagesize = getpagesize();
00232     mf->mapsize = (buf.st_size + pagesize - 1) / pagesize * pagesize;
00233 
00234     return mf;
00235 }
00236 
00237 void
00238 mmio_file_unmap(mmio_file_t *mf)
00239 {
00240     if (mf == NULL)
00241         return;
00242     if (munmap(mf->ptr, mf->mapsize) < 0) {
00243         E_ERROR_SYSTEM("Failed to unmap %ld bytes at %p", mf->mapsize, mf->ptr);
00244     }
00245     ckd_free(mf);
00246 }
00247 
00248 void *
00249 mmio_file_ptr(mmio_file_t *mf)
00250 {
00251     return mf->ptr;
00252 }
00253 #endif /* !__ADSPBLACKFIN__ */ 
00254 #endif /* !(WINCE || WIN32) */