2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
25 #include <be/kernel/fs_info.h>
26 #include <be/kernel/OS.h>
38 #include <sys/types.h>
39 #ifdef HAVE_SYS_INTTYPES_H
40 # include <sys/inttypes.h>
42 #ifdef HAVE_SYS_TIME_h
43 # include <sys/time.h>
46 #ifdef HAVE_SYS_IOCTL_H
47 #include <sys/ioctl.h>
54 #ifdef HAVE_SYS_MMAN_H
67 /***********************************************************************
71 int usleep (unsigned int useconds
)
76 #elif defined(__BEOS__)
77 return snooze(useconds
);
78 #elif defined(HAVE_SELECT)
81 delay
.tv_sec
= useconds
/ 1000000;
82 delay
.tv_usec
= useconds
% 1000000;
84 select( 0, 0, 0, 0, &delay
);
86 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
89 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
91 #endif /* HAVE_USLEEP */
93 /***********************************************************************
97 void *memmove( void *dest
, const void *src
, unsigned int len
)
99 register char *dst
= dest
;
101 /* Use memcpy if not overlapping */
102 if ((dst
+ len
<= (char *)src
) || ((char *)src
+ len
<= dst
))
104 memcpy( dst
, src
, len
);
106 /* Otherwise do it the hard way (FIXME: could do better than this) */
107 else if (dst
< (char *)src
)
109 while (len
--) *dst
++ = *((char *)src
)++;
114 src
= (char *)src
+ len
- 1;
115 while (len
--) *dst
-- = *((char *)src
)--;
119 #endif /* HAVE_MEMMOVE */
121 /***********************************************************************
124 #ifndef HAVE_STRERROR
125 const char *strerror( int err
)
127 /* Let's hope we have sys_errlist then */
128 return sys_errlist
[err
];
130 #endif /* HAVE_STRERROR */
133 /***********************************************************************
136 #ifndef HAVE_GETPAGESIZE
137 size_t getpagesize(void)
140 return sysconf(_SC_PAGESIZE
);
141 # elif defined(__i386__)
144 # error Cannot get the page size on this platform
147 #endif /* HAVE_GETPAGESIZE */
150 /***********************************************************************
153 #if !defined(HAVE_CLONE) && defined(__linux__)
154 int clone( int (*fn
)(void *), void *stack
, int flags
, void *arg
)
158 void **stack_ptr
= (void **)stack
;
159 *--stack_ptr
= arg
; /* Push argument on stack */
160 *--stack_ptr
= fn
; /* Push function pointer (popped into ebx) */
161 __asm__
__volatile__( "pushl %%ebx\n\t"
164 "popl %%ebx\n\t" /* Contains fn in the child */
165 "testl %%eax,%%eax\n\t"
167 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
168 "call *%%ebx\n\t" /* Should never return */
169 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
172 : "0" (SYS_clone
), "r" (flags
), "c" (stack_ptr
) );
173 assert( ret
); /* If ret is 0, we returned from the child function */
174 if (ret
> 0) return ret
;
180 #endif /* __i386__ */
182 #endif /* !HAVE_CLONE && __linux__ */
184 /***********************************************************************
187 #ifndef HAVE_STRCASECMP
188 int strcasecmp( const char *str1
, const char *str2
)
190 const unsigned char *ustr1
= (const unsigned char *)str1
;
191 const unsigned char *ustr2
= (const unsigned char *)str2
;
193 while (*ustr1
&& toupper(*ustr1
) == toupper(*ustr2
)) {
197 return toupper(*ustr1
) - toupper(*ustr2
);
199 #endif /* HAVE_STRCASECMP */
201 /***********************************************************************
204 #ifndef HAVE_STRNCASECMP
205 int strncasecmp( const char *str1
, const char *str2
, size_t n
)
207 const unsigned char *ustr1
= (const unsigned char *)str1
;
208 const unsigned char *ustr2
= (const unsigned char *)str2
;
212 while ((--n
> 0) && *ustr1
) {
213 if ((res
= toupper(*ustr1
) - toupper(*ustr2
))) return res
;
217 return toupper(*ustr1
) - toupper(*ustr2
);
219 #endif /* HAVE_STRNCASECMP */
221 /***********************************************************************
224 #ifndef HAVE_GETSOCKOPT
225 int getsockopt(int socket
, int level
, int option_name
,
226 void *option_value
, size_t *option_len
)
231 #endif /* !defined(HAVE_GETSOCKOPT) */
233 /***********************************************************************
236 #ifndef HAVE_INET_NETWORK
237 unsigned long inet_network(const char *cp
)
242 #endif /* defined(HAVE_INET_NETWORK) */
244 /***********************************************************************
248 int statfs(const char *name
, struct statfs
*info
)
259 if ((mydev
= dev_for_path(name
)) < 0) {
264 if (fs_stat_dev(mydev
,&fsinfo
) < 0) {
269 info
->f_bsize
= fsinfo
.block_size
;
270 info
->f_blocks
= fsinfo
.total_blocks
;
271 info
->f_bfree
= fsinfo
.free_blocks
;
273 #else /* defined(__BEOS__) */
276 #endif /* defined(__BEOS__) */
278 #endif /* !defined(HAVE_STATFS) */
281 /***********************************************************************
285 int lstat(const char *file_name
, struct stat
*buf
)
287 return stat( file_name
, buf
);
289 #endif /* HAVE_LSTAT */
291 /***********************************************************************
295 int mkstemp(char *tmpfn
)
300 xstart
= tmpfn
+strlen(tmpfn
)-1;
301 while ((xstart
> tmpfn
) && (*xstart
== 'X'))
305 char *newfn
= mktemp(tmpfn
);
307 if (!newfn
) /* something else broke horribly */
309 fd
= open(newfn
,O_CREAT
|O_RDWR
|O_EXCL
,0600);
313 /* fill up with X and try again ... */
314 while (*newfn
) *newfn
++ = 'X';
318 #endif /* HAVE_MKSTEMP */
321 /***********************************************************************
324 * FIXME: this is not thread-safe
327 ssize_t
pread( int fd
, void *buf
, size_t count
, off_t offset
)
332 if ((old_pos
= lseek( fd
, 0, SEEK_CUR
)) == -1) return -1;
333 if (lseek( fd
, offset
, SEEK_SET
) == -1) return -1;
334 if ((ret
= read( fd
, buf
, count
)) == -1)
336 int err
= errno
; /* save errno */
337 lseek( fd
, old_pos
, SEEK_SET
);
341 if (lseek( fd
, old_pos
, SEEK_SET
) == -1) return -1;
344 #endif /* HAVE_PREAD */
347 /***********************************************************************
350 * FIXME: this is not thread-safe
353 ssize_t
pwrite( int fd
, const void *buf
, size_t count
, off_t offset
)
358 if ((old_pos
= lseek( fd
, 0, SEEK_CUR
)) == -1) return -1;
359 if (lseek( fd
, offset
, SEEK_SET
) == -1) return -1;
360 if ((ret
= write( fd
, buf
, count
)) == -1)
362 int err
= errno
; /* save errno */
363 lseek( fd
, old_pos
, SEEK_SET
);
367 if (lseek( fd
, old_pos
, SEEK_SET
) == -1) return -1;
370 #endif /* HAVE_PWRITE */
373 #if defined(__svr4__) || defined(__NetBSD__)
374 /***********************************************************************
377 * The purpose of this routine is to emulate the behaviour of
378 * the Linux mmap() routine if a non-NULL address is passed,
379 * but the MAP_FIXED flag is not set. Linux in this case tries
380 * to place the mapping at the specified address, *unless* the
381 * range is already in use. Solaris, however, completely ignores
382 * the address argument in this case.
384 * As Wine code occasionally relies on the Linux behaviour, e.g. to
385 * be able to map non-relocateable PE executables to their proper
386 * start addresses, or to map the DOS memory to 0, this routine
387 * emulates the Linux behaviour by checking whether the desired
388 * address range is still available, and placing the mapping there
389 * using MAP_FIXED if so.
391 static int try_mmap_fixed (void *addr
, size_t len
, int prot
, int flags
,
392 int fildes
, off_t off
)
394 char * volatile result
= NULL
;
395 int pagesize
= getpagesize();
398 /* We only try to map to a fixed address if
399 addr is non-NULL and properly aligned,
400 and MAP_FIXED isn't already specified. */
404 if ( (uintptr_t)addr
& (pagesize
-1) )
406 if ( flags
& MAP_FIXED
)
409 /* We use vfork() to freeze all threads of the
410 current process. This allows us to check without
411 race condition whether the desired memory range is
412 already in use. Note that because vfork() shares
413 the address spaces between parent and child, we
414 can actually perform the mapping in the child. */
416 if ( (pid
= vfork()) == -1 )
418 perror("try_mmap_fixed: vfork");
426 /* We call mincore() for every page in the desired range.
427 If any of these calls succeeds, the page is already
428 mapped and we must fail. */
429 for ( i
= 0; i
< len
; i
+= pagesize
)
430 if ( mincore( (caddr_t
)addr
+ i
, pagesize
, &vec
) != -1 )
433 /* Perform the mapping with MAP_FIXED set. This is safe
434 now, as none of the pages is currently in use. */
435 result
= mmap( addr
, len
, prot
, flags
| MAP_FIXED
, fildes
, off
);
436 if ( result
== addr
)
439 if ( result
!= (void *) -1 ) /* This should never happen ... */
440 munmap( result
, len
);
445 /* vfork() lets the parent continue only after the child
446 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
447 so we don't need to wait for the child. */
449 return result
== addr
;
453 /***********************************************************************
456 * Portable wrapper for anonymous mmaps
458 void *wine_anon_mmap( void *start
, size_t size
, int prot
, int flags
)
461 static int fdzero
= -1;
468 if ((fdzero
= open( "/dev/zero", O_RDONLY
)) == -1)
470 perror( "/dev/zero: open" );
474 #endif /* MAP_ANON */
477 flags
&= ~MAP_SHARED
;
480 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
482 flags
|= MAP_PRIVATE
;
485 #if defined(__svr4__) || defined(__NetBSD__)
486 if ( try_mmap_fixed( start
, size
, prot
, flags
, fdzero
, 0 ) )
490 return mmap( start
, size
, prot
, flags
, fdzero
, 0 );
498 * These functions provide wrappers around dlopen() and associated
499 * functions. They work around a bug in glibc 2.1.x where calling
500 * a dl*() function after a previous dl*() function has failed
501 * without a dlerror() call between the two will cause a crash.
502 * They all take a pointer to a buffer that
503 * will receive the error description (from dlerror()). This
504 * parameter may be NULL if the error description is not required.
507 /***********************************************************************
510 void *wine_dlopen( const char *filename
, int flag
, char *error
, int errorsize
)
515 dlerror(); dlerror();
516 ret
= dlopen( filename
, flag
);
520 strncpy( error
, s
? s
: "", errorsize
);
521 error
[errorsize
- 1] = '\0';
528 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
529 error
[errorsize
- 1] = '\0';
535 /***********************************************************************
538 void *wine_dlsym( void *handle
, const char *symbol
, char *error
, int errorsize
)
543 dlerror(); dlerror();
544 ret
= dlsym( handle
, symbol
);
548 strncpy( error
, s
? s
: "", errorsize
);
549 error
[errorsize
- 1] = '\0';
556 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
557 error
[errorsize
- 1] = '\0';
563 /***********************************************************************
566 int wine_dlclose( void *handle
, char *error
, int errorsize
)
571 dlerror(); dlerror();
572 ret
= dlclose( handle
);
576 strncpy( error
, s
? s
: "", errorsize
);
577 error
[errorsize
- 1] = '\0';
584 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
585 error
[errorsize
- 1] = '\0';
591 /***********************************************************************
592 * wine_rewrite_s4tos2
594 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
595 * This is only practical if literal strings are writable.
597 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4
)
599 unsigned short *str2
,*s2
;
604 if ((*str4
& 0xffff0000) != 0) {
605 /* This string has already been converted. Return it as is */
606 return (unsigned short*)str4
;
609 /* Note that we can also end up here if the string has a single
610 * character. In such a case we will convert the string over and
611 * over again. But this is harmless.
613 str2
=s2
=(unsigned short*)str4
;
615 *s2
=(unsigned short)*str4
;
617 } while (*str4
++ != L
'\0');
624 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
625 * Fix/verify these implementations !
628 /***********************************************************************
631 char *ecvt (double number
, int ndigits
, int *decpt
, int *sign
)
633 static char buf
[40]; /* ought to be enough */
635 sprintf(buf
, "%.*e", ndigits
/* FIXME wrong */, number
);
636 *sign
= (number
< 0);
637 dec
= strchr(buf
, '.');
638 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
642 /***********************************************************************
645 char *fcvt (double number
, int ndigits
, int *decpt
, int *sign
)
647 static char buf
[40]; /* ought to be enough */
649 sprintf(buf
, "%.*e", ndigits
, number
);
650 *sign
= (number
< 0);
651 dec
= strchr(buf
, '.');
652 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
656 /***********************************************************************
659 * FIXME: uses both E and F.
661 char *gcvt (double number
, size_t ndigit
, char *buff
)
663 sprintf(buff
, "%.*E", (int)ndigit
, number
);
666 #endif /* HAVE_ECVT */
669 /***********************************************************************
670 * interlocked functions
676 __ASM_GLOBAL_FUNC(interlocked_cmpxchg
,
677 "movl 12(%esp),%eax\n\t"
678 "movl 8(%esp),%ecx\n\t"
679 "movl 4(%esp),%edx\n\t"
680 "lock; cmpxchgl %ecx,(%edx)\n\t"
682 __ASM_GLOBAL_FUNC(interlocked_cmpxchg_ptr
,
683 "movl 12(%esp),%eax\n\t"
684 "movl 8(%esp),%ecx\n\t"
685 "movl 4(%esp),%edx\n\t"
686 "lock; cmpxchgl %ecx,(%edx)\n\t"
688 __ASM_GLOBAL_FUNC(interlocked_xchg
,
689 "movl 8(%esp),%eax\n\t"
690 "movl 4(%esp),%edx\n\t"
691 "lock; xchgl %eax,(%edx)\n\t"
693 __ASM_GLOBAL_FUNC(interlocked_xchg_ptr
,
694 "movl 8(%esp),%eax\n\t"
695 "movl 4(%esp),%edx\n\t"
696 "lock; xchgl %eax,(%edx)\n\t"
698 __ASM_GLOBAL_FUNC(interlocked_xchg_add
,
699 "movl 8(%esp),%eax\n\t"
700 "movl 4(%esp),%edx\n\t"
701 "lock; xaddl %eax,(%edx)\n\t"
704 #elif defined(_MSC_VER)
706 __declspec(naked
) long interlocked_cmpxchg( long *dest
, long xchg
, long compare
)
708 __asm mov eax
, 12[esp
];
709 __asm mov ecx
, 8[esp
];
710 __asm mov edx
, 4[esp
];
711 __asm lock cmpxchg
[edx
], ecx
;
715 __declspec(naked
) void *interlocked_cmpxchg_ptr( void **dest
, void *xchg
, void *compare
)
717 __asm mov eax
, 12[esp
];
718 __asm mov ecx
, 8[esp
];
719 __asm mov edx
, 4[esp
];
720 __asm lock cmpxchg
[edx
], ecx
;
724 __declspec(naked
) long interlocked_xchg( long *dest
, long val
)
726 __asm mov eax
, 8[esp
];
727 __asm mov edx
, 4[esp
];
728 __asm lock xchg
[edx
], eax
;
732 __declspec(naked
) void *interlocked_xchg_ptr( void **dest
, void *val
)
734 __asm mov eax
, 8[esp
];
735 __asm mov edx
, 4[esp
];
736 __asm lock xchg
[edx
], eax
;
740 __declspec(naked
) long interlocked_xchg_add( long *dest
, long incr
)
742 __asm mov eax
, 8[esp
];
743 __asm mov edx
, 4[esp
];
744 __asm lock xadd
[edx
], eax
;
749 # error You must implement the interlocked* functions for your compiler
752 #elif defined(__powerpc__)
753 void* interlocked_cmpxchg_ptr( void **dest
, void* xchg
, void* compare
)
757 __asm__
__volatile__(
764 : "=&r"(ret
), "=&r"(scratch
)
765 : "r"(dest
), "r"(xchg
), "r"(compare
)
770 long interlocked_cmpxchg( long *dest
, long xchg
, long compare
)
774 __asm__
__volatile__(
781 : "=&r"(ret
), "=&r"(scratch
)
782 : "r"(dest
), "r"(xchg
), "r"(compare
)
787 long interlocked_xchg_add( long *dest
, long incr
)
791 __asm__
__volatile__(
792 "0: lwarx %0, %3, %1;"
794 " stwcx. %0, %3, %1;"
797 : "r"(dest
), "r"(incr
), "r"(zero
)
803 long interlocked_xchg( long* dest
, long val
)
806 __asm__
__volatile__(
811 : "r"(dest
), "r"(val
)
816 void* interlocked_xchg_ptr( void** dest
, void* val
)
819 __asm__
__volatile__(
824 : "r"(dest
), "r"(val
)
829 #elif defined(__sparc__) && defined(__sun__)
832 * As the earlier Sparc processors lack necessary atomic instructions,
833 * I'm simply falling back to the library-provided _lwp_mutex routines
834 * to ensure mutual exclusion in a way appropriate for the current
837 * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above)
838 * we could use this to speed up the Interlocked operations ...
841 static lwp_mutex_t interlocked_mutex
= DEFAULTMUTEX
;
843 long interlocked_cmpxchg( long *dest
, long xchg
, long compare
)
845 _lwp_mutex_lock( &interlocked_mutex
);
846 if (*dest
== compare
) *dest
= xchg
;
847 else compare
= *dest
;
848 _lwp_mutex_unlock( &interlocked_mutex
);
852 void *interlocked_cmpxchg_ptr( void **dest
, void *xchg
, void *compare
)
854 _lwp_mutex_lock( &interlocked_mutex
);
855 if (*dest
== compare
) *dest
= xchg
;
856 else compare
= *dest
;
857 _lwp_mutex_unlock( &interlocked_mutex
);
861 long interlocked_xchg( long *dest
, long val
)
864 _lwp_mutex_lock( &interlocked_mutex
);
867 _lwp_mutex_unlock( &interlocked_mutex
);
871 void *interlocked_xchg_ptr( void **dest
, void *val
)
874 _lwp_mutex_lock( &interlocked_mutex
);
877 _lwp_mutex_unlock( &interlocked_mutex
);
881 long interlocked_xchg_add( long *dest
, long incr
)
884 _lwp_mutex_lock( &interlocked_mutex
);
887 _lwp_mutex_unlock( &interlocked_mutex
);
891 # error You must implement the interlocked* functions for your CPU