1 /* $Id: ct_ncbimem.cpp 598667 2019-12-12 13:12:27Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: ncbimem.c
27 *
28 * Author: Gish, Kans, Ostell, Schuler
29 *
30 * Version Creation Date: 6/4/91
31 *
32 * C Tolkit Revision: 6.30
33 *
34 * File Description:
35 * portable memory handlers for Mac, PC, Unix
36 *
37 * ==========================================================================
38 */
39
40 #include <ncbi_pch.hpp>
41 #include <corelib/ncbifile.hpp>
42 #include <corelib/ncbistr.hpp>
43 #include <ctools/ctransition/ncbimem.hpp>
44 #include <ctools/ctransition/ncbistr.hpp>
45 #include <ctools/ctransition/ncbierr.hpp>
46
47 BEGIN_CTRANSITION_SCOPE
48
49
50 #ifdef OS_UNIX
51 #ifndef OS_UNIX_BEOS
52 /*#define USE_SETHEAPLIMIT*/
53 #undef USE_SETHEAPLIMIT
54 #endif
55 #endif
56
57 /* ! -- disable */
58 #undef USE_SETHEAPLIMIT
59
60 #ifdef USE_SETHEAPLIMIT
61 //#include <ncbithr.h>
62 #endif
63
64 /*#include <ncbiwin.h>*/
65
66 /* Used for UNIX memory-mapping. */
67 #ifdef MMAP_AVAIL
68 # ifdef OS_UNIX_LINUX
69 /* MADV_*** constants are not defined on Linux otherwise */
70 /*# define __USE_BSD*/
71 # endif
72 # include <sys/mman.h>
73 # ifdef OS_UNIX_AIX
74 # include <fcntl.h>
75 # else
76 # include <sys/fcntl.h>
77 # endif
78 # ifndef MAP_FAILED
79 # define MAP_FAILED ((void *) -1)
80 # endif
81 #endif
82
83 #ifdef USE_SETHEAPLIMIT
84 #include <sys/resource.h>
85 #endif
86
87
88
89 short g_bBadPtr;
90
91 static const char * _msgMemory = "Ran out of memory";
92
93
Nlm_CallocViaMalloc(size_t n_elem,size_t item_size)94 NLM_EXTERN void* Nlm_CallocViaMalloc(size_t n_elem, size_t item_size)
95 {
96 size_t size = n_elem * item_size;
97 void* ptr = Nlm_Malloc(size);
98 if ( ptr )
99 Nlm_MemSet(ptr, 0, size);
100 return ptr;
101 }
102
103
104
105 #ifdef USE_SETHEAPLIMIT
106 static size_t s_SetHeapLimit_Curr = 0;
107 static size_t s_SetHeapLimit_Add = 0;
108 static size_t s_SetHeapLimit_Max = 0;
109 static TNlmMutex s_SetHeapLimit_Mutex;
110
Nlm_SetHeapLimit(size_t curr,size_t add,size_t max)111 NLM_EXTERN Nlm_Boolean Nlm_SetHeapLimit(size_t curr, size_t add, size_t max)
112 {
113 Nlm_Boolean ok = FALSE;
114 struct rlimit rl;
115
116 if (NlmMutexLockEx(&s_SetHeapLimit_Mutex) != 0)
117 return FALSE;
118
119 if ( curr ) {
120 rl.rlim_cur = curr;
121 rl.rlim_max = RLIM_INFINITY;
122 }
123 else {
124 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
125 }
126
127 if (setrlimit(RLIMIT_DATA, &rl) == 0) {
128 s_SetHeapLimit_Curr = curr;
129 s_SetHeapLimit_Add = add;
130 s_SetHeapLimit_Max = max;
131 ok = TRUE;
132 }
133
134 NlmMutexUnlock(s_SetHeapLimit_Mutex);
135 return ok;
136 }
137
138 #else
Nlm_SetHeapLimit(size_t curr,size_t add,size_t max)139 NLM_EXTERN Nlm_Boolean Nlm_SetHeapLimit(size_t curr, size_t add, size_t max) {
140 return FALSE;
141 }
142 #endif /* USE_SETHEAPLIMIT */
143
144
145 typedef enum {
146 eA_Malloc,
147 eA_Calloc,
148 eA_Realloc
149 } EAllocator;
150
151 /****************************************************************************
152 *
153 * s_MemAllocator(ptr, size, flags, allocator)
154 * ptr -- origin pointer(for eA_Realloc only)
155 * size -- number of bytes to allocate
156 * flags -- any of the following bits may be set
157 * MGET_CLEAR clear to zeros
158 * MGET_ERRPOST post error on allocaion failure
159 * allocator -- method
160 *
161 * It is a generic routine for:
162 * Nlm_MemGet(size, flags)
163 * Nlm_MemNew(size)
164 * Nlm_MemMore(ptr, size)
165 * Nlm_MemExtend(ptr, size, oldsize)
166 *
167 ****************************************************************************/
168
169 static Nlm_Boolean post_mssg_for_mem_fail = FALSE;
170
171 extern void Nlm_SetMemFailFlag (Nlm_Boolean val);
Nlm_SetMemFailFlag(Nlm_Boolean val)172 extern void Nlm_SetMemFailFlag (Nlm_Boolean val)
173
174 {
175 post_mssg_for_mem_fail = val;
176 }
177
s_MemAllocator(void * ptr,size_t size,unsigned int flags,EAllocator allocator)178 static void* s_MemAllocator(void *ptr, size_t size,
179 unsigned int flags, EAllocator allocator)
180 {
181 void *x_ptr = 0;
182
183 switch ( allocator ) {
184 case eA_Malloc:
185 if ( !size )
186 return 0;
187 x_ptr = Nlm_Malloc(size);
188 break;
189 case eA_Calloc:
190 if ( !size )
191 return 0;
192 x_ptr = Nlm_Calloc(size, 1);
193 break;
194 case eA_Realloc:
195 if ( !ptr ) {
196 if (flags & MGET_ERRPOST)
197 ErrPostEx(SEV_WARNING, E_Programmer, 0, "Attempt to realloc NULL");
198 return 0;
199 }
200 if ( !size )
201 return Nlm_MemFree(ptr);
202
203 x_ptr = Nlm_Realloc(ptr, size);
204 break;
205 }
206
207 #ifdef USE_SETHEAPLIMIT
208 if (!x_ptr && s_SetHeapLimit_Curr) {
209 NlmMutexLock(s_SetHeapLimit_Mutex);
210
211 while (s_SetHeapLimit_Curr < s_SetHeapLimit_Max) {
212 struct rlimit rl;
213 size_t x_curr = s_SetHeapLimit_Curr + s_SetHeapLimit_Add;
214 if (x_curr > s_SetHeapLimit_Max)
215 x_curr = s_SetHeapLimit_Max;
216
217 if (flags & MGET_ERRPOST) {
218 ErrPostEx(SEV_WARNING, E_NoMemory, 0,
219 "Trying to allocate %ld bytes; "
220 "adjusting max.avail. heap size from %ld to %ld",
221 (long)size, (long)s_SetHeapLimit_Curr, (long)x_curr);
222 }
223
224 rl.rlim_cur = x_curr;
225 rl.rlim_max = RLIM_INFINITY;
226 if (setrlimit(RLIMIT_DATA, &rl) != 0)
227 break;
228
229 s_SetHeapLimit_Curr = x_curr;
230
231 switch ( allocator ) {
232 case eA_Malloc:
233 x_ptr = Nlm_Malloc(size);
234 break;
235 case eA_Calloc:
236 x_ptr = Nlm_Calloc(size, 1);
237 break;
238 case eA_Realloc:
239 x_ptr = Nlm_Realloc(ptr, size);
240 break;
241 }
242 if ( x_ptr )
243 break;
244 }
245
246 NlmMutexUnlock(s_SetHeapLimit_Mutex);
247 }
248 #endif /* USE_SETHEAPLIMIT */
249
250 if ( x_ptr ) {
251 if (flags & MGET_CLEAR)
252 memset(x_ptr, 0, size);
253 }
254 else if (flags & MGET_ERRPOST) {
255 if (post_mssg_for_mem_fail) {
256 Nlm_Message (MSG_OK, "Failed to allocate %ld bytes", (long)size);
257 }
258 ErrPostEx(SEV_FATAL, E_NoMemory, 0,
259 "Failed to allocate %ld bytes", (long)size);
260 }
261
262 return x_ptr;
263 }
264
265
Nlm_MemGet(size_t size,unsigned int flags)266 NLM_EXTERN void* LIBCALL Nlm_MemGet(size_t size, unsigned int flags)
267 {
268 return s_MemAllocator(0, size, flags, eA_Malloc);
269 }
270
Nlm_MemNew(size_t size)271 NLM_EXTERN void* LIBCALL Nlm_MemNew(size_t size)
272 {
273 return s_MemAllocator(0, size, MGET_ERRPOST, eA_Calloc);
274 }
275
Nlm_MemMore(void * ptr,size_t size)276 NLM_EXTERN void* LIBCALL Nlm_MemMore(void *ptr, size_t size)
277 {
278 return s_MemAllocator(ptr, size, MGET_ERRPOST, eA_Realloc);
279 }
280
Nlm_MemExtend(void * ptr,size_t size,size_t oldsize)281 NLM_EXTERN void* LIBCALL Nlm_MemExtend(void *ptr, size_t size, size_t oldsize)
282 {
283 void *x_ptr = s_MemAllocator(ptr, size, MGET_ERRPOST, eA_Realloc);
284 if (x_ptr && size > oldsize)
285 memset((char*)x_ptr + oldsize, 0, size - oldsize);
286
287 return x_ptr;
288 }
289
290
291 /*****************************************************************************
292 *
293 * Nlm_MemFree(ptr)
294 * frees allocated memory
295 *
296 *****************************************************************************/
297
Nlm_MemFree(void * ptr)298 NLM_EXTERN void * LIBCALL Nlm_MemFree (void *ptr)
299 {
300 if (ptr) {
301 free(ptr);
302 }
303 return NULL;
304 }
305
306
307 #if defined(_DEBUG) && defined(OS_MSWIN)
Nlm_MemFreeTrace(void * ptr,const char * module,const char * filename,int linenum)308 NLM_EXTERN void * LIBCALL Nlm_MemFreeTrace (void *ptr, const char *module,
309 const char *filename, int linenum)
310 {
311 if (ptr != NULL) {
312 free(ptr);
313 if (g_bBadPtr) {
314 ErrPostEx(SEV_WARNING,E_Programmer,0,
315 "MemFree: attempt to free invalid pointer");
316 }
317 }
318 return NULL;
319 }
320 #endif
321
322
323 /*****************************************************************************
324 *
325 * void Nlm_MemCopy(Pointer to, Pointer from, Uint4 bytes)
326 * WARNING: no check on overlapping regions
327 *
328 *****************************************************************************/
329
Nlm_MemCopy(void * dst,const void * src,size_t bytes)330 NLM_EXTERN void * LIBCALL Nlm_MemCopy (void *dst, const void *src, size_t bytes)
331 {
332 return (dst&&src) ? Nlm_MemCpy (dst, src, bytes) : NULL;
333 }
334
335 /*****************************************************************************
336 *
337 * void Nlm_MemDup (Pointer orig, Uint4 bytes)
338 * Duplicate the region of memory pointed to by 'orig' for 'size' length
339 *
340 *****************************************************************************/
341
Nlm_MemDup(const void * orig,size_t size)342 NLM_EXTERN void * LIBCALL Nlm_MemDup (const void *orig, size_t size)
343 {
344 Nlm_VoidPtr copy;
345
346 if (!orig || !size) {
347 return NULL;
348 }
349 copy = Nlm_Malloc(size);
350 if (!copy) {
351 ErrPostEx(SEV_FATAL, E_NoMemory, 0, _msgMemory);
352 return NULL;
353 }
354 Nlm_MemCpy(copy, orig, size);
355 return copy;
356 }
357
358 /*****************************************************************************
359 *
360 * void Nlm_MemMove (Pointer to, Pointer from, Uint4 bytes)
361 * This code will work on overlapping regions
362 *
363 *****************************************************************************/
364
Nlm_MemMove(void * dst,const void * src,size_t bytes)365 NLM_EXTERN void * LIBCALL Nlm_MemMove (void * dst, const void *src, size_t bytes)
366 {
367 register char *dest = (char*) dst;
368 register const char *sorc = (const char*) src;
369
370 if (dest > sorc) {
371 sorc += bytes;
372 dest += bytes;
373 while (bytes-- != 0) {
374 *--dest = *--sorc;
375 }
376 } else {
377 while (bytes-- != 0) {
378 *dest++ = *sorc++;
379 }
380 }
381 return dst;
382 }
383
384 /*****************************************************************************
385 *
386 * void Nlm_MemFill(to, value, bytes)
387 * set a block of memory to a value
388 *
389 *****************************************************************************/
390
Nlm_MemFill(void * buf,int value,size_t bytes)391 NLM_EXTERN void * LIBCALL Nlm_MemFill (void *buf, int value, size_t bytes)
392 {
393 return buf ? Nlm_MemSet (buf, value, bytes) : NULL;
394 }
395
396
397 /*****************************************************************************
398 *
399 * void Nlm_MemSearch(Pointer where, where_size, Pointer what, what_size)
400 * search a position one block of data into another
401 *
402 *****************************************************************************/
403
Nlm_MemSearch(const void * where,size_t where_size,const void * what,size_t what_size)404 NLM_EXTERN size_t LIBCALL Nlm_MemSearch(const void* where, size_t where_size,
405 const void* what, size_t what_size)
406 {
407 size_t i, rbound, pos;
408
409 rbound = where_size - what_size;
410 pos = (size_t)-1;
411 i = 0;
412 if (where_size && what_size && where_size >= what_size) {
413 while ((i <= rbound) && (pos == (size_t)-1)) {
414 if (memcmp((char*)where + i, what, what_size)==0)
415 pos = i;
416 else
417 i++;
418 }
419 }
420 return pos;
421 }
422
423
424 #if 0
425 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN) || defined(OS_MSWIN) || defined(MSC_VIRT)
426 /***** Handle functions are for Macintosh and Windows only *****/
427 /***** or Microsoft virtual memory manager ****/
428
429 static char * _msgNullHnd = "NULL handle passed as an argument";
430
431 #ifdef MSC_VIRT
432 Nlm_Boolean wrote_to_handle; /* used by ncbibs write routines */
433 #endif
434
435 /*****************************************************************************
436 *
437 * Nlm_HandGet(size, clear_out)
438 * returns handle to allocated memory
439 * if (clear_out) clear memory to 0
440 *
441 *****************************************************************************/
442
443 NLM_EXTERN Nlm_Handle LIBCALL Nlm_HandGet (size_t size, Nlm_Boolean clear_out)
444
445 {
446 Nlm_VoidPtr ptr;
447 Nlm_Handle hnd;
448
449 if (size == 0) return NULL;
450
451 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN)
452 hnd = (Nlm_Handle) NewHandle (size);
453 #endif
454
455 #ifdef OS_MSWIN
456 #ifdef _DLL
457 #ifdef WIN32
458 hnd = (Nlm_Handle) HeapAlloc(GetProcessHeap(), 0, size);
459 #else
460 hnd = (Nlm_Handle) GlobalAlloc (GMEM_MOVEABLE, size);
461 #endif
462 #else
463 hnd = (Nlm_Handle) malloc (size);
464 #endif
465 #endif
466
467 #ifdef MSC_VIRT
468 hnd = (Nlm_Handle) _vmalloc ((unsigned long)size);
469 #endif
470
471 if (hnd == NULL)
472 ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
473
474 else if (clear_out) {
475 #ifdef MSC_VIRT
476 wrote_to_handle = TRUE;
477 #endif
478 if ((ptr = HandLock (hnd)) != NULL)
479 Nlm_MemSet (ptr, 0, size);
480 HandUnlock (hnd);
481 }
482
483 return hnd;
484 }
485
486
487 /*****************************************************************************
488 *
489 * Nlm_HandNew(size)
490 *
491 *****************************************************************************/
492
493 NLM_EXTERN Nlm_Handle LIBCALL Nlm_HandNew (size_t size)
494
495 {
496 Nlm_Handle hnd;
497
498 if (size == 0) return NULL;
499
500 if ((hnd = HandGet (size, TRUE)) == NULL)
501 ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
502
503 return hnd;
504 }
505
506 /*****************************************************************************
507 *
508 * Nlm_HandMore(hnd, size)
509 *
510 *****************************************************************************/
511
512 NLM_EXTERN Nlm_Handle LIBCALL Nlm_HandMore (Nlm_Handle hnd, size_t size)
513
514 {
515 Nlm_Handle hnd2;
516
517 if (size == 0) {
518 Nlm_HandFree (hnd);
519 return NULL;
520 }
521
522 if (hnd == NULL) {
523 ErrPostEx(SEV_WARNING,E_Programmer,0,"HandMore: %s", _msgNullHnd);
524 return NULL;
525 }
526
527 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN)
528 SetHandleSize ((Handle)hnd, (Size)size);
529 hnd2 = hnd;
530 if (MemError() != noErr)
531 hnd2 = NULL;
532 #endif
533
534 #ifdef OS_MSWIN
535 #ifdef _DLL
536 #ifdef WIN32
537 hnd2 = (Nlm_Handle) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hnd, size);
538 #else
539 hnd2 = (Nlm_Handle) GlobalReAlloc ((HANDLE) hnd, size, GHND);
540 #endif
541 #else
542 hnd2 = (Nlm_Handle) realloc (hnd, size);
543 #endif
544 #endif
545
546 #ifdef MSC_VIRT
547 hnd2 = (Nlm_Handle) _vrealloc ((_vmhnd_t)hnd, (unsigned long)size);
548 #endif
549
550 if (hnd2 == NULL)
551 ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
552
553 return hnd2;
554 }
555
556
557 /*****************************************************************************
558 *
559 * Nlm_HandFree (hnd)
560 *
561 *****************************************************************************/
562
563 NLM_EXTERN Nlm_Handle LIBCALL Nlm_HandFree (Nlm_Handle hnd)
564 {
565 #ifdef MSC_VIRT
566 _vmhnd_t x;
567 #endif
568
569 if (hnd) {
570
571 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN)
572 DisposeHandle ((Handle) hnd);
573 #endif
574
575 #ifdef OS_MSWIN
576 #ifdef _DLL
577 #ifdef WIN32
578 HeapFree(GetProcessHeap(), 0, (HANDLE) hnd);
579 #else
580 GlobalFree ((HANDLE) hnd);
581 #endif
582 #else
583 free (hnd);
584 #endif
585 #endif
586
587 #ifdef MSC_VIRT
588 x = (_vmhnd_t)hnd;
589 while (_vlockcnt(x))
590 _vunlock(x, _VM_CLEAN);
591 _vfree(x);
592 #endif
593 }
594 else
595 ErrPostEx(SEV_WARNING,E_Programmer,0,"HandFree: %s", _msgNullHnd);
596
597 return NULL;
598 }
599
600
601 /*****************************************************************************
602 *
603 * Nlm_HandLock (hnd)
604 *
605 *****************************************************************************/
606
607 NLM_EXTERN Nlm_VoidPtr LIBCALL Nlm_HandLock (Nlm_Handle hnd)
608 {
609 Nlm_VoidPtr ptr;
610
611 if (hnd == NULL) {
612 ErrPostEx(SEV_WARNING,E_Programmer,0,"HandLock: %s", _msgNullHnd);
613 return NULL;
614 }
615
616 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN)
617 HLock ((Handle) hnd);
618 ptr = *((Handle) hnd);
619 #endif
620
621 #ifdef OS_MSWIN
622 #ifdef _DLL
623 #ifdef WIN32
624 ptr = hnd;
625 #else
626 ptr = GlobalLock ((HANDLE) hnd);
627 #endif
628 #else
629 ptr = hnd;
630 #endif
631 #endif
632
633 #ifdef MSC_VIRT
634 ptr = _vlock((_vmhnd_t) hnd);
635 #endif
636
637 return ptr;
638 }
639
640 /*****************************************************************************
641 *
642 * Nlm_HandUnlock(hnd)
643 *
644 *****************************************************************************/
645
646 NLM_EXTERN Nlm_VoidPtr LIBCALL Nlm_HandUnlock (Nlm_Handle hnd)
647 {
648 #ifdef MSC_VIRT
649 int dirty = _VM_CLEAN;
650 #endif
651
652 if (hnd == NULL)
653 ErrPostEx(SEV_WARNING,E_Programmer,0,"HandUnlock: %s", _msgNullHnd);
654 else {
655 #if defined(OS_MAC) || defined(OS_UNIX_DARWIN)
656 HUnlock ((Handle) hnd);
657 #endif
658
659 #ifdef OS_MSWIN
660 #ifdef _DLL
661 #ifdef WIN32
662 /* nothing */
663 #else
664 GlobalUnlock ((HANDLE) hnd);
665 #endif
666 #else
667 /* nothing */
668 #endif
669 #endif
670
671 #ifdef MSC_VIRT
672 if (wrote_to_handle == TRUE)
673 dirty = _VM_DIRTY;
674 _vunlock ((_vmhnd_t) hnd, dirty); /* always assume dirty */
675 wrote_to_handle = FALSE;
676 #endif
677 }
678
679 return NULL;
680 }
681
682 #endif /* Mac or Win */
683 #endif /*0*/
684
685
686
687 #ifdef _WINDLL
688 /*****************************************************************************
689 *
690 * Windows DLL-specific functions (shared memory)
691 *
692 * dll_Malloc
693 * dll_Calloc (not yet)
694 * dll_Realloc (not yet)
695 * dll_Free
696 *
697 *****************************************************************************/
698
699
dll_Malloc(size_t bytes)700 void * dll_Malloc (size_t bytes)
701 {
702 HGLOBAL hMem;
703 void *pMem;
704
705 if (bytes >0 && (hMem = GlobalAlloc(GMEM_DDESHARE,bytes)))
706 {
707 if (pMem = GlobalLock(hMem))
708 return pMem;
709 else
710 GlobalFree(hMem);
711 }
712
713 TRACE("dll_Malloc(%ld) failed\n",bytes);
714 return NULL;
715 }
716
dll_Free(void * pMem)717 void dll_Free (void *pMem)
718 {
719 HGLOBAL hMem = GlobalHandle(pMem);
720 GlobalUnlock(hMem);
721 GlobalFree(hMem);
722 }
723 #endif /* _WINDLL */
724
725
726 /*********************************************************************
727 * Function to test whether memory-mapping is available.
728 *
729 * returns TRUE if it is supported by NCBI routines.
730 *********************************************************************/
731
Nlm_MemMapAvailable(void)732 NLM_EXTERN Nlm_Boolean Nlm_MemMapAvailable(void)
733 {
734 #if defined(MMAP_AVAIL) || defined(WIN32)
735 return TRUE;
736 #else
737 return FALSE;
738 #endif
739 }
740
741
Nlm_MemMapInit(const Nlm_Char PNTR name)742 NLM_EXTERN Nlm_MemMapPtr Nlm_MemMapInit(const Nlm_Char PNTR name)
743 {
744 Nlm_MemMapPtr mem_mapp;
745 if (!Nlm_MemMapAvailable() || !name || !*name ||
746 (mem_mapp = (Nlm_MemMapPtr)Nlm_MemNew(sizeof(Nlm_MemMap))) == NULL)
747 return NULL;
748
749 for (;;) {{ /* (quasi-TRY block) */
750 if ((mem_mapp->file_size = NCBI_NS_NCBI::CFile(name).GetLength()) < 0)
751 break;
752
753 if (mem_mapp->file_size == 0) /* Special case */
754 return mem_mapp;
755
756 #ifdef WIN32
757 {{
758 char x_name[MAX_PATH], *str;
759 Nlm_StringNCpy_0(x_name, name, sizeof(x_name));
760 for (str = x_name; *str; str++)
761 if (*str == '\\')
762 *str = '/'; /* name of a file-mapping object cannot contain '\' */
763
764 if ( !(mem_mapp->hMap =
765 OpenFileMapping(FILE_MAP_READ, FALSE, _T_XCSTRING(x_name))) )
766 { /* If failed to attach to an existing file-mapping object then
767 * create a new one(based on the specified file) */
768 HANDLE hFile= CreateFile(_T_XCSTRING(name), GENERIC_READ, FILE_SHARE_READ, NULL,
769 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
770 if (hFile == INVALID_HANDLE_VALUE)
771 break;
772
773 mem_mapp->hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY,
774 0, 0, _T_XCSTRING(x_name));
775 CloseHandle( hFile );
776 if ( !mem_mapp->hMap )
777 break;
778 }
779
780 if ( !(mem_mapp->mmp_begin = (Nlm_CharPtr)
781 MapViewOfFile(mem_mapp->hMap, FILE_MAP_READ,
782 0, 0, mem_mapp->file_size)) ) {
783 CloseHandle( mem_mapp->hMap );
784 break;
785 }
786 }}
787
788 #elif defined(MMAP_AVAIL)
789 {{ /* UNIX memory mapping. */
790 int fd = open(name, O_RDONLY);
791 if (fd < 0)
792 break;
793
794 mem_mapp->mmp_begin = (Nlm_CharPtr) mmap(NULL, mem_mapp->file_size,
795 PROT_READ, MAP_PRIVATE, fd, 0);
796 close(fd);
797 if ((void*) mem_mapp->mmp_begin == (void*) MAP_FAILED)
798 break;
799 }}
800 #endif
801
802 /* Success */
803 return mem_mapp;
804 }}
805
806 /* Error; cleanup */
807 Nlm_MemFree(mem_mapp);
808 return NULL;
809 }
810
811
Nlm_MemMapFini(Nlm_MemMapPtr mem_mapp)812 NLM_EXTERN void Nlm_MemMapFini(Nlm_MemMapPtr mem_mapp)
813 {
814 if ( !mem_mapp )
815 return;
816
817 #ifdef WIN32
818 UnmapViewOfFile( mem_mapp->mmp_begin );
819 if ( mem_mapp->hMap )
820 CloseHandle( mem_mapp->hMap );
821 #elif defined(MMAP_AVAIL)
822 munmap(mem_mapp->mmp_begin, mem_mapp->file_size);
823 #endif
824
825 Nlm_MemFree(mem_mapp);
826 }
827
828
Nlm_MemMapAdvise(void * addr,size_t len,EMemMapAdvise advise)829 NLM_EXTERN Nlm_Boolean Nlm_MemMapAdvise(void* addr, size_t len, EMemMapAdvise advise)
830 {
831 #if defined(HAVE_MADVISE) && defined(MADV_NORMAL)
832 int adv;
833 if (!addr || !len) {
834 return FALSE;
835 }
836 switch (advise) {
837 case eMMA_Random:
838 adv = MADV_RANDOM; break;
839 case eMMA_Sequential:
840 adv = MADV_SEQUENTIAL; break;
841 case eMMA_WillNeed:
842 adv = MADV_WILLNEED; break;
843 case eMMA_DontNeed:
844 adv = MADV_DONTNEED; break;
845 default:
846 adv = MADV_NORMAL;
847 }
848 /* Conversion type of "addr" to char* -- Sun Solaris fix */
849 return madvise((char*)addr, len, adv) == 0;
850 #else
851 return TRUE;
852 #endif
853 }
854
855
Nlm_MemMapAdvisePtr(Nlm_MemMapPtr ptr,EMemMapAdvise advise)856 NLM_EXTERN Nlm_Boolean Nlm_MemMapAdvisePtr(Nlm_MemMapPtr ptr, EMemMapAdvise advise)
857 {
858 #if defined(HAVE_MADVISE) && defined(MADV_NORMAL)
859 return ptr ? Nlm_MemMapAdvise(ptr->mmp_begin, ptr->file_size, advise) : FALSE;
860 #else
861 return TRUE;
862 #endif
863 }
864
865
866 END_CTRANSITION_SCOPE
867