Initial commit
This commit is contained in:
44
libsst-os/Makefile
Normal file
44
libsst-os/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
# libsst-os/Makefile
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 12/23/2011
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# Makefile for libsst-os
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
BINNAME := $(DIST)/libsst-os.a
|
||||
ifeq ($(TARGET),debug)
|
||||
BINNAME := $(subst .a,_d.a, $(BINNAME))
|
||||
endif
|
||||
|
||||
include sources-$(SUBSYSTEM).mk
|
||||
|
||||
OBJ := $(addprefix obj/$(ARCH)/$(TARGET)/,$(subst .c,.o,$(SRC))) obj/$(ARCH)/$(TARGET)/SST_CPUCache_$(ARCH).o
|
||||
|
||||
$(shell mkdir -p obj/$(ARCH)/$(TARGET))
|
||||
|
||||
$(BINNAME): $(OBJ)
|
||||
$(AR) cru $@ $+
|
||||
$(RANLIB) $@
|
||||
|
||||
# CLEAN
|
||||
clean:
|
||||
@-rm -r -f obj $(DIST)/libsst-os*.a
|
||||
|
||||
# *.c files to *.o files
|
||||
obj/$(ARCH)/$(TARGET)/%.o: %.c
|
||||
@echo CC $@
|
||||
@$(CC) $(CFLAGS) -c $*.c -o obj/$(ARCH)/$(TARGET)/$*.o
|
||||
|
||||
# *.asm files to *.o files
|
||||
obj/$(ARCH)/$(TARGET)/%.o: %.asm
|
||||
@echo ASM $@
|
||||
@$(ASM) $*.asm -o obj/$(ARCH)/$(TARGET)/$*.o
|
||||
57
libsst-os/POSIXPrivate.h
Normal file
57
libsst-os/POSIXPrivate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
POSIXPrivate.h
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Private data structures for POSIX implementation of libsst-os. Not to be distributed
|
||||
as part of public SDK headers.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _POSIXPRIVATE_H
|
||||
#define _POSIXPRIVATE_H
|
||||
|
||||
/* We *really* want 64-bit support */
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <pstdint.h>
|
||||
|
||||
#include <stdlib.h> /* size_t, malloc(), free()*/
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h> /* mmap(), mprotect(), munmap(), etc. */
|
||||
|
||||
/******************************************************************************/
|
||||
typedef struct SST_File_POSIX
|
||||
{
|
||||
int fd;
|
||||
int isAsync; /* Is this file in async mode */
|
||||
|
||||
#ifdef _DEBUG
|
||||
int nrMmaps; /* Number of outstanding memory maps */
|
||||
#endif
|
||||
} SST_File_POSIX;
|
||||
|
||||
typedef struct SST_MemoryMap_POSIX
|
||||
{
|
||||
uint64_t offset; /* Offset parameter as given to SST_OS_MmapCreate() */
|
||||
size_t len; /* Length parameter as given to SST_OS_MmapCreate() */
|
||||
void* base; /* Returned base address from SST_OS_MmapCreate() */
|
||||
|
||||
#ifdef _DEBUG
|
||||
SST_File_POSIX* owner; /* File that created this memory map */
|
||||
#endif
|
||||
} SST_MemoryMap_POSIX;
|
||||
|
||||
#endif
|
||||
118
libsst-os/SST_Alloc.c
Normal file
118
libsst-os/SST_Alloc.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
SST_Alloc.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 1/7/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Provides portable implementations for various CRT-like memory functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Alloc.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
#include <stdio.h>
|
||||
#include <pstdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define OVERFLOW_MESSAGE "Multiplication overflow in memory allocation"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_AlignPtr(void* ptr, size_t boundary)
|
||||
{
|
||||
if ((((uintptr_t)ptr) % boundary) == 0)
|
||||
return ptr;
|
||||
|
||||
return (void*)((uintptr_t)ptr + (boundary) - ((uintptr_t)ptr % boundary));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_AlignedMalloc(size_t bytes, size_t boundary)
|
||||
{
|
||||
uintptr_t mask;
|
||||
uintptr_t addr;
|
||||
unsigned char delta;
|
||||
void* base;
|
||||
unsigned char* backptr;
|
||||
|
||||
if(boundary == 0 || boundary > UCHAR_MAX)
|
||||
return NULL;
|
||||
|
||||
mask = (uintptr_t)(boundary - 1);
|
||||
|
||||
/* Check if not a power 2 */
|
||||
if(boundary & mask)
|
||||
return NULL;
|
||||
|
||||
/* Allocate memory with some slack space */
|
||||
base = malloc(bytes + boundary);
|
||||
if(base == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Get aligned address. It'll be somewhere in the extra slackspace that we just malloc()'d */
|
||||
addr = ((uintptr_t)base + boundary - 1) & mask;
|
||||
|
||||
/* Address was already aligned...but the free function expects a backtrack amount */
|
||||
if(addr == (uintptr_t)base)
|
||||
addr += boundary;
|
||||
|
||||
delta = (unsigned char)((addr - (uintptr_t)base) & 0xFF);
|
||||
|
||||
backptr = (unsigned char*)(addr-1);
|
||||
*backptr = delta-1;
|
||||
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_AlignedFree(void* ptr)
|
||||
{
|
||||
unsigned char* back = ((unsigned char*)ptr) - 1;
|
||||
unsigned char delta;
|
||||
|
||||
delta = *back;
|
||||
|
||||
back = back - delta;
|
||||
|
||||
free(back);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_SafeAlignedMalloc(size_t nelem, size_t elsize, size_t boundary)
|
||||
{
|
||||
if(nelem > SIZE_MAX/elsize)
|
||||
{
|
||||
SST_OS_RuntimeError(OVERFLOW_MESSAGE);
|
||||
|
||||
/* If app just swallows the error, then return NULL */
|
||||
return NULL;
|
||||
}
|
||||
return SST_OS_AlignedMalloc(nelem*elsize, boundary);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_SafeRealloc(void* ptr, size_t nelem, size_t elsize)
|
||||
{
|
||||
if(nelem > SIZE_MAX/elsize)
|
||||
{
|
||||
SST_OS_RuntimeError(OVERFLOW_MESSAGE);
|
||||
|
||||
/* If app just swallows the error, then return NULL */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return realloc(ptr, nelem * elsize);
|
||||
}
|
||||
44
libsst-os/SST_Assert.c
Normal file
44
libsst-os/SST_Assert.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
SST_Assert.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os common assert functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Assert.h>
|
||||
#include <stdlib.h> /* NULL */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_AssertHandlerFunc sst_debug_assert_handler = NULL; /* Handler function for debug asserts */
|
||||
void* sst_debug_assert_handler_arg = NULL; /* Argument to the debug assert */
|
||||
SST_AssertHandlerFunc sst_runtime_assert_handler = NULL; /* Handler function for runtime asserts */
|
||||
void* sst_runtime_assert_handler_arg = NULL; /* Argument to the runtime assert */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_SetDebugAssertHandler(SST_AssertHandlerFunc _func, void *_arg)
|
||||
{
|
||||
sst_debug_assert_handler = _func;
|
||||
sst_debug_assert_handler_arg = _arg;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_SetRuntimeAssertHandler(SST_AssertHandlerFunc _func, void *_arg)
|
||||
{
|
||||
sst_runtime_assert_handler = _func;
|
||||
sst_runtime_assert_handler_arg = _arg;
|
||||
}
|
||||
74
libsst-os/SST_Assert_Generic.c
Normal file
74
libsst-os/SST_Assert_Generic.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
SST_Assert_Generic.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os assert functions portable for any system with a C standard library
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#include <stdio.h> /* printf() */
|
||||
#include <stdlib.h> /* abort() */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_RuntimeAssertImpl(int condition, const char* condString, const char* msgString, const char* file, const char* func, int line)
|
||||
{
|
||||
/* Assume likely success and exit early */
|
||||
if(condition)
|
||||
return;
|
||||
|
||||
/* Call the runtime handler if we have one */
|
||||
if (sst_runtime_assert_handler != 0)
|
||||
if(sst_runtime_assert_handler(msgString, sst_runtime_assert_handler_arg))
|
||||
return;
|
||||
|
||||
printf("The application has reached a runtime assertion failure! This means a serious problem has occurred and the program needs to close.\n\nProgrammer Info:\n\nFile \"%s\", line (%d) in function \"%s()\".\n\nFailed condition: \"%s\"\n\n"
|
||||
,
|
||||
file,
|
||||
line,
|
||||
func,
|
||||
condString);
|
||||
|
||||
#ifdef _DEBUG
|
||||
PORTABLE_TRAP();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_RuntimeAssertImplNoInfo(int cond, const char* msgString)
|
||||
{
|
||||
/* Assume likely success and exit early */
|
||||
if(cond)
|
||||
return;
|
||||
|
||||
/* Call the runtime handler if we have one */
|
||||
if (sst_runtime_assert_handler != 0)
|
||||
if(sst_runtime_assert_handler(msgString, sst_runtime_assert_handler_arg))
|
||||
return;
|
||||
|
||||
printf("The application has reached a runtime assertion failure! This means a serious problem has occurred, and the application needs to close.\n");
|
||||
|
||||
#ifdef _DEBUG
|
||||
PORTABLE_TRAP();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
157
libsst-os/SST_Assert_Win32.c
Normal file
157
libsst-os/SST_Assert_Win32.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
SST_Assert_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os assert functions for Win32 systems (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS /* Shhh, compiler */
|
||||
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <stdio.h> /* sprintf() */
|
||||
|
||||
/*************************************************************************/
|
||||
void SST_OS_RuntimeAssertImpl(int condition, const char* condString, const char* msgString, const char* file, const char* func, int line)
|
||||
{
|
||||
UINT flags;
|
||||
char buf[2048];
|
||||
int retcode;
|
||||
|
||||
/* Assume likely success and exit early */
|
||||
if(condition)
|
||||
return;
|
||||
|
||||
/* Call the runtime handler if we have one */
|
||||
if (sst_runtime_assert_handler != 0)
|
||||
retcode = sst_runtime_assert_handler(msgString, sst_runtime_assert_handler_arg);
|
||||
else
|
||||
retcode = 0;
|
||||
|
||||
/* See if user handler returned non-zero (i.e. don't raise error) */
|
||||
if(retcode != 0)
|
||||
return;
|
||||
|
||||
sprintf(buf, "The application has reached a runtime assertion failure! Normally, this means a serious problem, and the program should close.\n\nProgrammer Info:\n\nFile \"%s\", line (%d) in function \"%s()\".\n\nFailed condition: \"%s\"\n\n"
|
||||
|
||||
#ifdef _DEBUG
|
||||
"Terminate application? (Click \"Cancel\" to debug)\n\n"
|
||||
#endif
|
||||
,
|
||||
file,
|
||||
line,
|
||||
func,
|
||||
condString);
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
flags = MB_YESNOCANCEL | MB_ICONERROR;
|
||||
#else
|
||||
flags = MB_OK | MB_ICONERROR;
|
||||
#endif
|
||||
retcode = MessageBoxA(NULL, buf, "libSST: Runtime assertion failure!", flags);
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
switch(retcode)
|
||||
{
|
||||
/* Yes -- terminate process */
|
||||
case IDYES:
|
||||
ExitProcess((UINT)line);
|
||||
/* No 'break' -- function never returns */
|
||||
|
||||
/* No -- just continue */
|
||||
case IDNO:
|
||||
return;
|
||||
|
||||
/* Cancel -- debug it */
|
||||
case IDCANCEL:
|
||||
PORTABLE_TRAP();
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Ignore return value in release mode, just exit using the line number as the exit code. Since this is non-zero, it should signal to the OS that there was a problem. */
|
||||
(void)retcode;
|
||||
ExitProcess((UINT)line);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_RuntimeAssertImplNoInfo(int cond, const char* msgString)
|
||||
{
|
||||
UINT flags;
|
||||
int retcode;
|
||||
|
||||
/* Assume likely success and exit early */
|
||||
if(cond)
|
||||
return;
|
||||
|
||||
/* Call the runtime handler if we have one */
|
||||
if (sst_runtime_assert_handler != 0)
|
||||
retcode = sst_runtime_assert_handler(msgString, sst_runtime_assert_handler_arg);
|
||||
else
|
||||
retcode = 0;
|
||||
|
||||
/* See if user handler returned non-zero (i.e. don't raise error) */
|
||||
if(retcode != 0)
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
flags = MB_YESNOCANCEL | MB_ICONERROR;
|
||||
#else
|
||||
flags = MB_OK | MB_ICONERROR;
|
||||
#endif
|
||||
retcode = MessageBoxA(NULL,
|
||||
/* Message */
|
||||
#ifdef _DEBUG
|
||||
"The application has reached a runtime assertion failure! Normally, this means a serious problem has occurred, and the program should close.\n\n"
|
||||
"Terminate application?"
|
||||
#else /* Release doesn't have an option to not close */
|
||||
"The application has reached a runtime assertion failure! This means a serious problem has occurred, and the application needs to close."
|
||||
#endif
|
||||
,
|
||||
|
||||
"libSST: Runtime assertion failure!", flags);
|
||||
|
||||
#ifdef _DEBUG
|
||||
switch(retcode)
|
||||
{
|
||||
/* No -- just continue */
|
||||
case IDNO:
|
||||
return;
|
||||
|
||||
/* Cancel -- debug it */
|
||||
case IDCANCEL:
|
||||
PORTABLE_TRAP();
|
||||
break;
|
||||
|
||||
/* Yes -- terminate process */
|
||||
case IDYES:
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Ignore return value in release mode, just exit. */
|
||||
(void)retcode;
|
||||
#endif
|
||||
|
||||
/* dead code :( */
|
||||
ExitProcess(0xdeadc0de);
|
||||
}
|
||||
|
||||
|
||||
41
libsst-os/SST_CPUCache_arm.asm
Normal file
41
libsst-os/SST_CPUCache_arm.asm
Normal file
@@ -0,0 +1,41 @@
|
||||
@ SST_CPUCache_arm.asm
|
||||
@ Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
@ Created: 6/21/2012
|
||||
@
|
||||
@ Purpose:
|
||||
@
|
||||
@ 32-bit assembly for ARMv6+ CPU cache functions. Assembles with GNU as
|
||||
@
|
||||
@ License:
|
||||
@
|
||||
@ This program is free software. It comes without any warranty, to
|
||||
@ the extent permitted by applicable law. You can redistribute it
|
||||
@ and/or modify it under the terms of the Do What The Fuck You Want
|
||||
@ To Public License, Version 2, as published by Sam Hocevar. See
|
||||
@ http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
.text
|
||||
|
||||
@ ELF symbol names
|
||||
.global SST_OS_GetCacheLineSize
|
||||
.global SST_OS_FlushDCRange
|
||||
.global SST_OS_InvalidateICRange
|
||||
.global SST_OS_SyncCache
|
||||
|
||||
|
||||
@ uint32_t SST_OS_GetCacheLineSize()
|
||||
SST_OS_GetCacheLineSize:
|
||||
bx lr
|
||||
|
||||
@ void SST_OS_FlushDCRange(void* base, size_t range)
|
||||
SST_OS_FlushDCRange:
|
||||
bx lr
|
||||
|
||||
@ void SST_OS_InvalidateICRange(void* base, size_t range)
|
||||
SST_OS_InvalidateICRange:
|
||||
bx lr
|
||||
|
||||
|
||||
@ void SST_OS_SyncCache()
|
||||
SST_OS_SyncCache:
|
||||
bx lr
|
||||
38
libsst-os/SST_CPUCache_ia64.asm
Normal file
38
libsst-os/SST_CPUCache_ia64.asm
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
SST_CPUCache_ia64.asm
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 4/16/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Itanium assembly for CPU cache functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
//Functions
|
||||
.global SST_OS_GetCacheLineSize#
|
||||
.global SST_OS_FlushDCRange#
|
||||
.global SST_OS_InvalidateICRange#
|
||||
.global SST_OS_SyncCache#
|
||||
|
||||
.section .text
|
||||
|
||||
/* uint32_t SST_OS_GetCacheLineSize() */
|
||||
.align 32
|
||||
SST_OS_GetCacheLineSize:
|
||||
|
||||
/* SST_OS_InvalidateICRange(void* base, size_t range) */
|
||||
SST_OS_InvalidateICRange:
|
||||
SST_OS_FlushDCRange:
|
||||
|
||||
/* void SST_OS_SyncCache() */
|
||||
SST_OS_SyncCache:
|
||||
br.ret.sptk.many b0;;
|
||||
46
libsst-os/SST_CPUCache_mips.asm
Normal file
46
libsst-os/SST_CPUCache_mips.asm
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
SST_CPUCache_mips.asm
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 7/20/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
32-bit assembly for MIPS CPU cache functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/* ELF symbol names */
|
||||
.global SST_OS_GetCacheLineSize
|
||||
.global SST_OS_FlushDCRange
|
||||
.global SST_OS_InvalidateICRange
|
||||
.global SST_OS_SyncCache
|
||||
|
||||
|
||||
/* uint32_t SST_OS_GetCacheLineSize() */
|
||||
SST_OS_GetCacheLineSize:
|
||||
jr $ra
|
||||
li $v0, 64
|
||||
|
||||
/* SST_OS_InvalidateICRange(void* base, size_t range) */
|
||||
SST_OS_InvalidateICRange:
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
SST_OS_FlushDCRange:
|
||||
sync
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
/* void SST_OS_SyncCache() */
|
||||
SST_OS_SyncCache:
|
||||
sync
|
||||
jr $ra
|
||||
nop
|
||||
41
libsst-os/SST_CPUCache_ppc.asm
Normal file
41
libsst-os/SST_CPUCache_ppc.asm
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
SST_CPUCache_ppc.asm
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 7/20/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
32-bit assembly for Power Architecture CPU cache functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/* ELF symbol names */
|
||||
.global SST_OS_GetCacheLineSize
|
||||
.global SST_OS_FlushDCRange
|
||||
.global SST_OS_InvalidateICRange
|
||||
.global SST_OS_SyncCache
|
||||
|
||||
|
||||
/* uint32_t SST_OS_GetCacheLineSize() */
|
||||
SST_OS_GetCacheLineSize:
|
||||
li r3, 64
|
||||
blr
|
||||
|
||||
/* SST_OS_InvalidateICRange(void* base, size_t range) */
|
||||
SST_OS_InvalidateICRange:
|
||||
SST_OS_FlushDCRange:
|
||||
blr
|
||||
|
||||
/* void SST_OS_SyncCache() */
|
||||
SST_OS_SyncCache:
|
||||
sync
|
||||
isync
|
||||
blr
|
||||
50
libsst-os/SST_CPUCache_sparc.asm
Normal file
50
libsst-os/SST_CPUCache_sparc.asm
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
SST_CPUCache_sparc.asm
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
32-bit assembly for SPARCv9 CPU cache functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/* ELF symbol names */
|
||||
.global SST_OS_GetCacheLineSize
|
||||
.global SST_OS_FlushDCRange
|
||||
.global SST_OS_InvalidateICRange
|
||||
.global SST_OS_SyncCache
|
||||
|
||||
|
||||
/* uint32_t SST_OS_GetCacheLineSize() */
|
||||
SST_OS_GetCacheLineSize:
|
||||
retl
|
||||
or %g0, 64, %o0 /* kludge: it's 64. */
|
||||
|
||||
/* SST_OS_InvalidateICRange(void* base, size_t range) */
|
||||
SST_OS_InvalidateICRange:
|
||||
SST_OS_FlushDCRange:
|
||||
add %o0, %o1, %o2 /* %o2 = end address */
|
||||
|
||||
1:
|
||||
flush %o0
|
||||
cmp %o0, %o2
|
||||
bcs %icc,1b /* branch on less than (unsigned) */
|
||||
add %o0, 8, %o0 /* FLUSH insn flushes a double word at a time */
|
||||
|
||||
retl
|
||||
nop
|
||||
|
||||
/* void SST_OS_SyncCache() */
|
||||
SST_OS_SyncCache:
|
||||
membar #Sync
|
||||
retl
|
||||
nop
|
||||
49
libsst-os/SST_CPUCache_sparc64.asm
Normal file
49
libsst-os/SST_CPUCache_sparc64.asm
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
SST_CPUCache_sparc64.asm
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
64-bit assembly for SPARCv9 CPU cache functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
.global SST_OS_GetCacheLineSize
|
||||
.global SST_OS_FlushDCRange
|
||||
.global SST_OS_InvalidateICRange
|
||||
.global SST_OS_SyncCache
|
||||
|
||||
|
||||
/* uint32_t SST_OS_GetCacheLineSize() */
|
||||
SST_OS_GetCacheLineSize:
|
||||
retl
|
||||
or %g0, 64, %o0 /* kludge: it's 64. */
|
||||
|
||||
/* SST_OS_InvalidateICRange(void* base, size_t range) */
|
||||
SST_OS_InvalidateICRange:
|
||||
SST_OS_FlushDCRange:
|
||||
add %o0, %o1, %o2 /* %o2 = end address */
|
||||
|
||||
1:
|
||||
flush %o0
|
||||
cmp %o0, %o2
|
||||
bcs %xcc,1b /* branch on less than (unsigned) */
|
||||
add %o0, 8, %o0 /* FLUSH insn flushes a double word at a time */
|
||||
|
||||
retl
|
||||
nop
|
||||
|
||||
/* void SST_OS_SyncCache() */
|
||||
SST_OS_SyncCache:
|
||||
membar #Sync
|
||||
retl
|
||||
nop
|
||||
76
libsst-os/SST_CPUCache_x86-64-win64.asm
Normal file
76
libsst-os/SST_CPUCache_x86-64-win64.asm
Normal file
@@ -0,0 +1,76 @@
|
||||
; SST_CPUCache_x86-64-win64.asm
|
||||
; Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
; Created: 12/23/2011
|
||||
;
|
||||
; Purpose:
|
||||
;
|
||||
; 64-bit assembly for x86 CPU cache functions for the Microsoft x64 ABI. Assembles with YASM 1.1/NASM 2.0+
|
||||
;
|
||||
; License:
|
||||
;
|
||||
; This program is free software. It comes without any warranty, to
|
||||
; the extent permitted by applicable law. You can redistribute it
|
||||
; and/or modify it under the terms of the Do What The Fuck You Want
|
||||
; To Public License, Version 2, as published by Sam Hocevar. See
|
||||
; http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
; Win64 and UNIX calling conventions differ for x64-64. I know, it's absurd.
|
||||
; Because of this, there are separate implementation for Win64 and x64-64 UNIX (Linux, *BSD, Solaris, MacOS X, etc.)
|
||||
; Here is the break down:
|
||||
;
|
||||
; REGISTER | Win64 | UNIX
|
||||
;-----------+-----------+----------
|
||||
;rax | Retval | Retval
|
||||
;rsi | Not used | 1st arg
|
||||
;rdi | Not used | 2nd arg
|
||||
;rcx | 1st arg | 3rd arg
|
||||
;rdx | 2nd arg | 4th arg
|
||||
;r8 | 3rd arg | 5th arg
|
||||
;r9 | 4th arg | 6th arg
|
||||
|
||||
[bits 64]
|
||||
[segment .text]
|
||||
|
||||
; Win64 symbol names
|
||||
[global SST_OS_GetCacheLineSize]
|
||||
[global SST_OS_FlushDCRange]
|
||||
[global SST_OS_InvalidateICRange]
|
||||
[global SST_OS_SyncCache]
|
||||
|
||||
|
||||
;uint32_t SST_OS_GetCacheLineSize()
|
||||
SST_OS_GetCacheLineSize:
|
||||
push rbx
|
||||
mov eax, 0x80000006 ;Cache info command
|
||||
cpuid
|
||||
movzx rax, cl ;ECX bits 0-7 = L2 cache line size (TODO: what about L1?)
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
;SST_OS_InvalidateICRange(void* base, size_t range)
|
||||
SST_OS_InvalidateICRange:
|
||||
|
||||
;A jmp instruction is sufficient. x86 CPUs have self-snooping caches.
|
||||
jmp do_serialize
|
||||
do_serialize:
|
||||
|
||||
ret
|
||||
|
||||
; void SST_OS_SyncCache()
|
||||
SST_OS_SyncCache:
|
||||
mfence
|
||||
ret
|
||||
|
||||
;void SST_OS_FlushDCRange(void* base, size_t range)
|
||||
SST_OS_FlushDCRange:
|
||||
call SST_OS_GetCacheLineSize ;Get the cache line size
|
||||
|
||||
dc_flush_more2: ;do {
|
||||
clflush [rsi]
|
||||
add rsi, rax ;base += cache_line_size
|
||||
sub rdi, rax ;range -= cache_line_size
|
||||
|
||||
cmp rcx, 0
|
||||
jg dc_flush_more2 ; } while(range > 0)
|
||||
|
||||
ret
|
||||
78
libsst-os/SST_CPUCache_x86-64.asm
Normal file
78
libsst-os/SST_CPUCache_x86-64.asm
Normal file
@@ -0,0 +1,78 @@
|
||||
; SST_CPUCache_x86-64.asm
|
||||
; Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
; Created: 12/23/2011
|
||||
;
|
||||
; Purpose:
|
||||
;
|
||||
; 64-bit assembly for x86 CPU cache functions for the SysV ABI. Assembles with YASM 1.1/NASM 2.0+
|
||||
;
|
||||
; License:
|
||||
;
|
||||
; This program is free software. It comes without any warranty, to
|
||||
; the extent permitted by applicable law. You can redistribute it
|
||||
; and/or modify it under the terms of the Do What The Fuck You Want
|
||||
; To Public License, Version 2, as published by Sam Hocevar. See
|
||||
; http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
; Win64 and UNIX calling conventions differ for x64-64. I know, it's absurd.
|
||||
; Because of this, there are separate implementation for Win64 and x64-64 UNIX (Linux, *BSD, Solaris, MacOS X, etc.)
|
||||
; Here is the break down:
|
||||
;
|
||||
; REGISTER | Win64 | UNIX
|
||||
;-----------+-----------+----------
|
||||
;rax | Retval | Retval
|
||||
;rsi | Not used | 1st arg
|
||||
;rdi | Not used | 2nd arg
|
||||
;rcx | 1st arg | 3rd arg
|
||||
;rdx | 2nd arg | 4th arg
|
||||
;r8 | 3rd arg | 5th arg
|
||||
;r9 | 4th arg | 6th arg
|
||||
|
||||
[bits 64]
|
||||
[segment .text]
|
||||
|
||||
; ELF symbol names
|
||||
[global SST_OS_GetCacheLineSize]
|
||||
[global SST_OS_FlushDCRange]
|
||||
[global SST_OS_InvalidateICRange]
|
||||
[global SST_OS_SyncCache]
|
||||
|
||||
|
||||
;uint32_t SST_OS_GetCacheLineSize()
|
||||
;no args, so win64 and unix abis are the same
|
||||
SST_OS_GetCacheLineSize:
|
||||
push rbx
|
||||
mov eax, 0x80000006 ;Cache info command
|
||||
cpuid
|
||||
movzx rax, cl ;ECX bits 0-7 = L2 cache line size (TODO: what about L1?)
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
;SST_OS_InvalidateICRange(void* base, size_t range)
|
||||
SST_OS_InvalidateICRange:
|
||||
|
||||
;A jmp instruction is sufficient. x86 CPUs have self-snooping caches.
|
||||
jmp do_serialize
|
||||
do_serialize:
|
||||
|
||||
ret
|
||||
|
||||
; void SST_OS_SyncCache()
|
||||
SST_OS_SyncCache:
|
||||
mfence
|
||||
ret
|
||||
|
||||
;void SST_OS_FlushDCRange(void* base, size_t range)
|
||||
SST_OS_FlushDCRange:
|
||||
|
||||
call SST_OS_GetCacheLineSize ;Get the cache line size
|
||||
|
||||
dc_flush_more1: ;do {
|
||||
clflush [rcx]
|
||||
add rcx, rax ;base += cache_line_size
|
||||
sub rdx, rax ;range -= cache_line_size
|
||||
|
||||
cmp rcx, 0
|
||||
jg dc_flush_more1 ; } while(range > 0)
|
||||
|
||||
ret
|
||||
77
libsst-os/SST_CPUCache_x86.asm
Normal file
77
libsst-os/SST_CPUCache_x86.asm
Normal file
@@ -0,0 +1,77 @@
|
||||
; SST_CPUCache_x86.asm
|
||||
; Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
; Created: 12/23/2011
|
||||
;
|
||||
; Purpose:
|
||||
;
|
||||
; 32-bit assembly for x86 CPU cache functions. Assembles with YASM 1.1/NASM 2.0+
|
||||
;
|
||||
; License:
|
||||
;
|
||||
; This program is free software. It comes without any warranty, to
|
||||
; the extent permitted by applicable law. You can redistribute it
|
||||
; and/or modify it under the terms of the Do What The Fuck You Want
|
||||
; To Public License, Version 2, as published by Sam Hocevar. See
|
||||
; http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
[bits 32]
|
||||
[segment .text]
|
||||
|
||||
; Win32 symbol names
|
||||
[global _SST_OS_GetCacheLineSize]
|
||||
[global _SST_OS_FlushDCRange]
|
||||
[global _SST_OS_InvalidateICRange]
|
||||
[global _SST_OS_SyncCache]
|
||||
|
||||
; ELF symbol names
|
||||
[global SST_OS_GetCacheLineSize]
|
||||
[global SST_OS_FlushDCRange]
|
||||
[global SST_OS_InvalidateICRange]
|
||||
[global SST_OS_SyncCache]
|
||||
|
||||
|
||||
;uint32_t SST_OS_GetCacheLineSize()
|
||||
_SST_OS_GetCacheLineSize:
|
||||
SST_OS_GetCacheLineSize:
|
||||
push ebx
|
||||
mov eax, 0x80000006 ;Cache info command
|
||||
cpuid
|
||||
movzx eax, cl ;ECX bits 0-7 = L2 cache line size (TODO: what about L1?)
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
;void SST_OS_FlushDCRange(void* base, size_t range)
|
||||
_SST_OS_FlushDCRange:
|
||||
SST_OS_FlushDCRange:
|
||||
|
||||
call SST_OS_GetCacheLineSize ;Get the cache line size
|
||||
|
||||
mov edx, [esp+4] ;edx = base
|
||||
mov ecx, [esp+8] ;ecx = range (in bytes)
|
||||
|
||||
dc_flush_more: ;do {
|
||||
clflush [edx]
|
||||
add edx, eax ;base += cache_line_size
|
||||
sub ecx, eax ;range -= cache_line_size
|
||||
|
||||
cmp ecx, 0
|
||||
jg dc_flush_more ; } while(range > 0)
|
||||
|
||||
ret
|
||||
|
||||
;SST_OS_InvalidateICRange(void* base, size_t range)
|
||||
_SST_OS_InvalidateICRange:
|
||||
SST_OS_InvalidateICRange:
|
||||
|
||||
;A jmp instruction is sufficient. x86 CPUs have self-snooping caches.
|
||||
jmp do_serialize
|
||||
do_serialize:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
; void SST_OS_SyncCache()
|
||||
_SST_OS_SyncCache:
|
||||
SST_OS_SyncCache:
|
||||
mfence
|
||||
ret
|
||||
94
libsst-os/SST_CPU_POSIX.c
Normal file
94
libsst-os/SST_CPU_POSIX.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
SST_CPU_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os CPU querying functions for POSIX systems
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
The POSIX doesn't actually provide much in the terms of CPU
|
||||
querying. Other source files provide specific operating systems
|
||||
implementations (e.g: Linux, Solaris, ...)
|
||||
*/
|
||||
|
||||
|
||||
#include "POSIXPrivate.h"
|
||||
#include <SST/SST_CPU.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberCPUChips()
|
||||
{
|
||||
/* 0 -> no information available */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberPhysicalCPUs(void)
|
||||
{
|
||||
/* 0 -> no information available */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberLogicalCPUs(void)
|
||||
{
|
||||
return (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_MapPhysicalToLogicalCPU(int physCpuId, int* logCpuIds)
|
||||
{
|
||||
(void)physCpuId;
|
||||
(void)logCpuIds;
|
||||
/* 0 -> API not available */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetCPUAffinity(unsigned char* cpuMaskReturn, unsigned int cpuMaskSize)
|
||||
{
|
||||
SST_OS_DebugAssert(cpuMaskReturn != NULL, "CPU mask may not be NULL");
|
||||
|
||||
(void)cpuMaskReturn;
|
||||
(void)cpuMaskSize;
|
||||
return 0; /* NYI */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_SetCPUAffinity(const unsigned char* cpuMask, unsigned int cpuMaskSize)
|
||||
{
|
||||
SST_OS_DebugAssert(cpuMask != NULL, "CPU mask may not be NULL");
|
||||
|
||||
(void)cpuMask;
|
||||
(void)cpuMaskSize;
|
||||
return 0; /* NYI */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_SetPreferredCPU(int logCpuId)
|
||||
{
|
||||
(void)logCpuId;
|
||||
|
||||
/* Hint ignored */
|
||||
return;
|
||||
}
|
||||
354
libsst-os/SST_CPU_Win32.c
Normal file
354
libsst-os/SST_CPU_Win32.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
SST_CPU_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os CPU querying functions for Win32 systems (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <malloc.h> /* _alloca() */
|
||||
|
||||
#include <SST/SST_CPU.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
/*
|
||||
SUPPORT FOR > 64 CPUS
|
||||
----------------------
|
||||
This code does its best to be compatible with large numbers of logical CPUs. Processor groups are
|
||||
a bit weird, see MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/dd405503(v=vs.85).aspx)
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static const uint8_t popbits[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* popcount of an 8-bit value */
|
||||
static uint8_t popcount8(uint8_t v)
|
||||
{
|
||||
return popbits[v & 0x0Fu] + popbits[v>>4];
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* popcount on the Win32 KAFFINITY value (64-bit value) */
|
||||
static int popcount(KAFFINITY mask)
|
||||
{
|
||||
int count = 0, i;
|
||||
|
||||
for(i=0; i<sizeof(KAFFINITY); i++)
|
||||
{
|
||||
/* No more bits set? */
|
||||
if(!mask)
|
||||
break;
|
||||
|
||||
count += popcount8(mask & 0xFF);
|
||||
|
||||
mask >>= 8;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberCPUChips()
|
||||
{
|
||||
DWORD length = 0;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION* relat;
|
||||
DWORD nr;
|
||||
int nrChips = 0;
|
||||
|
||||
/* Query data structure size */
|
||||
GetLogicalProcessorInformation(NULL, &length);
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return -1;
|
||||
|
||||
/* Really get the info this time */
|
||||
relat = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)_alloca((size_t)length);
|
||||
if(GetLogicalProcessorInformation(relat, &length) == FALSE)
|
||||
return -2;
|
||||
|
||||
/* Scan list */
|
||||
nr = length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
|
||||
while(nr > 0)
|
||||
{
|
||||
if(relat->Relationship == RelationProcessorPackage)
|
||||
nrChips++;
|
||||
|
||||
relat++;
|
||||
nr--;
|
||||
}
|
||||
|
||||
return nrChips;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberPhysicalCPUs(void)
|
||||
{
|
||||
DWORD length = 0;
|
||||
char* ptr, *end;
|
||||
int nrCores = 0;
|
||||
|
||||
/* Query data structure size */
|
||||
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return -1;
|
||||
|
||||
/* Really get the info this time */
|
||||
ptr = (char*)_alloca((size_t)length);
|
||||
end = ptr + length;
|
||||
if(GetLogicalProcessorInformationEx(
|
||||
RelationProcessorCore,
|
||||
(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr,
|
||||
&length) == FALSE)
|
||||
return -2;
|
||||
|
||||
while(ptr < end)
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr;
|
||||
nrCores++;
|
||||
|
||||
ptr += (size_t)info->Size;
|
||||
}
|
||||
|
||||
return nrCores;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_GetNumberLogicalCPUs(void)
|
||||
{
|
||||
DWORD length = 0;
|
||||
char* ptr, *end;
|
||||
int nrThreads = 0;
|
||||
|
||||
/* Query data structure size */
|
||||
GetLogicalProcessorInformationEx(RelationProcessorPackage, NULL, &length);
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return -1;
|
||||
|
||||
/* Really get the info this time */
|
||||
ptr = (char*)_alloca((size_t)length);
|
||||
end = ptr + length;
|
||||
if(GetLogicalProcessorInformationEx(
|
||||
RelationProcessorPackage,
|
||||
(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr,
|
||||
&length) == FALSE)
|
||||
return -2;
|
||||
|
||||
while(ptr < end)
|
||||
{
|
||||
WORD i;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr;
|
||||
|
||||
for(i=0; i<info->Processor.GroupCount; i++)
|
||||
nrThreads += popcount(info->Processor.GroupMask[i].Mask);
|
||||
|
||||
|
||||
ptr += info->Size;
|
||||
}
|
||||
|
||||
return nrThreads;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_MapPhysicalToLogicalCPU(int physCpuId, int* logCpuIds)
|
||||
{
|
||||
DWORD length = 0;
|
||||
char* ptr, *end;
|
||||
WORD i;
|
||||
int j;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info;
|
||||
|
||||
SST_OS_DebugAssert(logCpuIds != NULL, "The return array for logical CPUs may not be NULL");
|
||||
|
||||
/* Query data structure size */
|
||||
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return -2;
|
||||
|
||||
/* Really get the info this time */
|
||||
ptr = (char*)_alloca((size_t)length);
|
||||
end = ptr + length;
|
||||
if(GetLogicalProcessorInformationEx(
|
||||
RelationProcessorCore,
|
||||
(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr,
|
||||
&length) == FALSE)
|
||||
return -3;
|
||||
|
||||
info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)ptr;
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
/* Figure out how many elements in this array */
|
||||
int nr = (int)(length / info->Size);
|
||||
|
||||
/* Bounds checking */
|
||||
SST_OS_DebugAssert(!(physCpuId >= nr), "Array too small to contain logical CPUs. Use SST_OS_GetNumberLogicalCPUs() to determine correct size");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This union is large, so we can't just do info[index], we have to do
|
||||
'base_address + size * index'. Ugly, but necessary. */
|
||||
info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(ptr + (size_t)(info->Size*physCpuId));
|
||||
|
||||
j = 0; /* j = number of logical CPUs mapped */
|
||||
for(i=0; i<info->Processor.GroupCount; i++)
|
||||
{
|
||||
/* Figure out base logical CPU ID for processor group. Usually 64 CPUs / group. */
|
||||
int groupbase = (int)(info->Processor.GroupMask[i].Group * 8 * sizeof(KAFFINITY));
|
||||
size_t k;
|
||||
KAFFINITY mask = info->Processor.GroupMask[i].Mask;
|
||||
|
||||
/*
|
||||
Algorithm: Each GROUP_AFFINITY structure has a mask. Scan through it and
|
||||
if bit 'k' is set, then add 'k+groupbase' to the array.
|
||||
*/
|
||||
|
||||
/* Scan through bits and add logical CPUs */
|
||||
for(k=0; k<(8 * sizeof(KAFFINITY)); k++)
|
||||
{
|
||||
/* No more bits set */
|
||||
if(!mask)
|
||||
break;
|
||||
|
||||
/* Is this bit set? */
|
||||
if(mask & 1)
|
||||
{
|
||||
/* Add the logical CPU to the array */
|
||||
logCpuIds[j] = (int)k + groupbase;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Next bit... */
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of logical CPUs written to logCpuIds[] */
|
||||
return j;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_GetCPUAffinity(unsigned char* cpuMaskReturn, unsigned int cpuMaskSize)
|
||||
{
|
||||
WORD maxGroup;
|
||||
GROUP_AFFINITY aff;
|
||||
SST_OS_DebugAssert(cpuMaskReturn != NULL, "CPU mask may not be NULL");
|
||||
SST_OS_DebugAssert(cpuMaskSize > 0, "CPU mask may not be zero");
|
||||
|
||||
/* Calculate the maximum number of groups that can be stored using the space provided */
|
||||
maxGroup = (WORD)(cpuMaskSize / sizeof(KAFFINITY));
|
||||
if(cpuMaskSize % sizeof(KAFFINITY))
|
||||
maxGroup += 1;
|
||||
|
||||
if(maxGroup == 0)
|
||||
return -1;
|
||||
|
||||
memset(cpuMaskReturn, 0, cpuMaskSize);
|
||||
|
||||
GetThreadGroupAffinity(GetCurrentThread(), &aff);
|
||||
|
||||
/* Ensure the real processor group doesn't exceed provided space */
|
||||
if(aff.Group < maxGroup)
|
||||
{
|
||||
uint32_t byteOffset = aff.Group * sizeof(KAFFINITY); /* i.e. where to begin in cpuMaskReturn[] */
|
||||
uint32_t bytesLeft = cpuMaskSize - byteOffset; /* i.e. how many bytes are left */
|
||||
uint32_t i;
|
||||
KAFFINITY mask = aff.Mask;
|
||||
unsigned char* maskReturn = cpuMaskReturn + byteOffset;
|
||||
|
||||
for(i=0; i<bytesLeft; i++)
|
||||
{
|
||||
if(!mask)
|
||||
break;
|
||||
|
||||
maskReturn[i] = (uint8_t)(mask & 0xFF);
|
||||
|
||||
mask >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_SetCPUAffinity(const unsigned char* cpuMask, unsigned int cpuMaskSize)
|
||||
{
|
||||
uint8_t groupPopCount[4096/(sizeof(KAFFINITY) * 8)];
|
||||
KAFFINITY groupMask[4096/(sizeof(KAFFINITY) * 8)];
|
||||
uint8_t lowest = UINT8_MAX;
|
||||
uint8_t lowestGroup = 0;
|
||||
unsigned int i;
|
||||
GROUP_AFFINITY aff;
|
||||
|
||||
|
||||
SST_OS_DebugAssert(cpuMask != NULL, "CPU mask may not be NULL");
|
||||
|
||||
|
||||
/* Windows only allows a thread to be a member of a single processor group, which makes sense
|
||||
when you consider that migrating threads across NUMA nodes is a bad idea. Here, we select the
|
||||
processor group that has the fewest bits set (except for 0...) */
|
||||
if(cpuMaskSize > 4096) /* Disallow arbitrarily large masks. 4096 processors is fine, really */
|
||||
cpuMaskSize = 4096;
|
||||
|
||||
memset(groupPopCount, 0, sizeof(groupPopCount));
|
||||
memset(groupMask, 0, sizeof(groupMask));
|
||||
|
||||
/* Operate on each byte */
|
||||
for(i=0; i<cpuMaskSize; i++)
|
||||
{
|
||||
uint8_t groupIndex = (uint8_t)(i / sizeof(KAFFINITY)); /* i is in bytes, sizeof() is in bytes */
|
||||
uint8_t groupByte = (uint8_t)(i % 8);
|
||||
|
||||
/* Sum all popcount8() of the bytes that make up a processor group's mask */
|
||||
groupPopCount[groupIndex] += popcount8(cpuMask[i]);
|
||||
|
||||
/* OR the 8-bit mask into KAFFINITY values (essentially merge them) */
|
||||
groupMask[groupIndex] |= (KAFFINITY)cpuMask[i] << (KAFFINITY)(groupByte * 8);
|
||||
|
||||
/* Record the smallest group that is not 0 */
|
||||
if(groupPopCount[groupIndex] > 0 && groupPopCount[groupIndex] < lowest)
|
||||
lowest = groupIndex;
|
||||
}
|
||||
|
||||
|
||||
aff.Group = (WORD)((uint16_t)lowestGroup);
|
||||
aff.Mask = groupMask[lowestGroup];
|
||||
|
||||
SetThreadGroupAffinity(GetCurrentThread(), &aff, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_SetPreferredCPU(int logCpuId)
|
||||
{
|
||||
PROCESSOR_NUMBER ideal;
|
||||
|
||||
SST_OS_DebugAssert(logCpuId < SST_OS_GetNumberLogicalCPUs(), "Logical CPU ID is out of range");
|
||||
|
||||
ideal.Group = (WORD)logCpuId / (WORD)(sizeof(KAFFINITY)*8);
|
||||
ideal.Number = (WORD)logCpuId % (WORD)(sizeof(KAFFINITY)*8);
|
||||
ideal.Reserved = 0;
|
||||
|
||||
SetThreadIdealProcessorEx(GetCurrentThread(), &ideal, NULL);
|
||||
}
|
||||
77
libsst-os/SST_DynLib_POSIX.c
Normal file
77
libsst-os/SST_DynLib_POSIX.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SST_DynLib_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os dynamic linking functions for POSIX systems
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_DynLib.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_DynLib SST_OS_LoadDynLib(const char* path)
|
||||
{
|
||||
SST_OS_DebugAssert(path != NULL, "Path may not be NULL");
|
||||
|
||||
|
||||
return (SST_DynLib)dlopen(path, RTLD_LAZY);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_DynLibFunc SST_OS_GetLibSymbol(SST_DynLib lib, const char* symbol)
|
||||
{
|
||||
uintptr_t tmp;
|
||||
|
||||
SST_OS_DebugAssert(lib != NULL, "Library may not be NULL");
|
||||
SST_OS_DebugAssert(symbol != NULL, "Library may not be NULL");
|
||||
|
||||
tmp = (uintptr_t)dlsym((void*)lib, symbol);
|
||||
|
||||
return (SST_DynLibFunc)tmp;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_CloseDynLib(SST_DynLib lib)
|
||||
{
|
||||
SST_OS_DebugAssert(lib != NULL, "Library may not be NULL");
|
||||
|
||||
dlclose((void*)lib);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_DynLibName(char* libnameOut, const char* libnameIn)
|
||||
{
|
||||
SST_OS_DebugAssert(libnameIn != NULL, "Library name may not be NULL");
|
||||
|
||||
if(libnameOut == NULL)
|
||||
return 3+(int)strlen(libnameIn)+3; /* strlen("lib")+strlen(libnameIn)+strlen(".so") */
|
||||
|
||||
libnameOut[0] = 'l'; /* strcpy(libnameOut, "lib") */
|
||||
libnameOut[1] = 'i';
|
||||
libnameOut[2] = 'b';
|
||||
|
||||
strcpy(libnameOut+3, libnameIn);
|
||||
strcat(libnameOut, ".so");
|
||||
|
||||
return 0;
|
||||
}
|
||||
66
libsst-os/SST_DynLib_Win32.c
Normal file
66
libsst-os/SST_DynLib_Win32.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
SST_DynLib_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os dynamic linking functions for Win32 systems (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <SST/SST_Assert.h>
|
||||
#include <SST/SST_DynLib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_DynLib SST_OS_LoadDynLib(const char* path)
|
||||
{
|
||||
SST_OS_DebugAssert(path != NULL, "Path may not be NULL");
|
||||
|
||||
return (SST_DynLib)LoadLibraryExA(path, NULL, 0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_DynLibFunc SST_OS_GetLibSymbol(SST_DynLib lib, const char* symbol)
|
||||
{
|
||||
SST_OS_DebugAssert(lib != NULL, "Library may not be NULL");
|
||||
SST_OS_DebugAssert(symbol != NULL, "Library may not be NULL");
|
||||
|
||||
return (SST_DynLibFunc)GetProcAddress((HMODULE)lib, symbol);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_CloseDynLib(SST_DynLib lib)
|
||||
{
|
||||
SST_OS_DebugAssert(lib != NULL, "Library may not be NULL");
|
||||
|
||||
FreeLibrary((HMODULE)lib);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_DynLibName(char* libnameOut, const char* libnameIn)
|
||||
{
|
||||
SST_OS_DebugAssert(libnameIn != NULL, "Library name may not be NULL");
|
||||
|
||||
if(libnameOut == NULL)
|
||||
return (int)strlen(libnameIn)+4; /* +strlen(".dll") */
|
||||
|
||||
strcpy(libnameOut, libnameIn);
|
||||
strcat(libnameOut, ".dll");
|
||||
|
||||
return 0;
|
||||
}
|
||||
70
libsst-os/SST_Endian.c
Normal file
70
libsst-os/SST_Endian.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SST_Endian.c
|
||||
Author: Chris Ertel <crertel@762studios.com>
|
||||
Created: 1/16/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os endian and byte reordering routines.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Endian.h>
|
||||
#include <pstdint.h>
|
||||
|
||||
static SST_ByteOrder machineByteOrder;
|
||||
|
||||
void __libsst_init_endian()
|
||||
{
|
||||
const uint16_t testSeq = 0x55FE;
|
||||
const uint8_t* c = (const uint8_t*)&testSeq;
|
||||
|
||||
if(c[0] == 0x55)
|
||||
machineByteOrder = SST_BIG_ENDIAN;
|
||||
else
|
||||
machineByteOrder = SST_LITTLE_ENDIAN;
|
||||
}
|
||||
|
||||
SST_ByteOrder SST_OS_GetHostEndianness( void )
|
||||
{
|
||||
return machineByteOrder;
|
||||
}
|
||||
|
||||
uint16_t SST_OS_ByteSwap16( uint16_t _toSwap)
|
||||
{
|
||||
return (_toSwap >> 8) | (_toSwap << 8);
|
||||
}
|
||||
|
||||
uint32_t SST_OS_ByteSwap32( uint32_t _toSwap)
|
||||
{
|
||||
uint32_t a = (_toSwap & 0x000000ff);
|
||||
uint32_t b = (_toSwap & 0x0000ff00) >> 8;
|
||||
uint32_t c = (_toSwap & 0x00ff0000) >> 16;
|
||||
uint32_t d = (_toSwap & 0xff000000) >> 24;
|
||||
|
||||
uint32_t ret = (a << 24) | (b << 16) | (c << 8) | (d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t SST_OS_ByteSwap64( uint64_t _toSwap)
|
||||
{
|
||||
uint64_t a = (_toSwap & 0x00000000000000ffull);
|
||||
uint64_t b = (_toSwap & 0x000000000000ff00ull) >> 8;
|
||||
uint64_t c = (_toSwap & 0x0000000000ff0000ull) >> 16;
|
||||
uint64_t d = (_toSwap & 0x00000000ff000000ull) >> 24;
|
||||
uint64_t e = (_toSwap & 0x000000ff00000000ull) >> 32;
|
||||
uint64_t f = (_toSwap & 0x0000ff0000000000ull) >> 40;
|
||||
uint64_t g = (_toSwap & 0x00ff000000000000ull) >> 48;
|
||||
uint64_t h = (_toSwap & 0xff00000000000000ull) >> 56;
|
||||
|
||||
uint64_t ret = (a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h;
|
||||
return ret;
|
||||
}
|
||||
191
libsst-os/SST_FileSys_POSIX.c
Normal file
191
libsst-os/SST_FileSys_POSIX.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
SST_FileSys_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/31/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os file system querying for POSIX systems
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_FileSys.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* In order to get alloca() on Solaris, <alloca.h> is needed */
|
||||
#if defined(__SUNPRO_C)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
/* No PATH_MAX symbol */
|
||||
#if !defined(PATH_MAX)
|
||||
|
||||
#if defined(_POSIX_PATH_MAX) &&
|
||||
#define PATH_MAX _POSIX_PATH_MAX
|
||||
#else
|
||||
#define PATH_MAX 256 /* This is what _POSIX_PATH_MAX must be according to POSIX */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct SST_Dir_POSIX
|
||||
{
|
||||
char* canonPath;
|
||||
size_t canonPathLen;
|
||||
DIR* dirp;
|
||||
} SST_Dir_POSIX;
|
||||
|
||||
SST_Dir SST_OS_OpenDirectory(const char* path)
|
||||
{
|
||||
size_t len;
|
||||
char* canonPath;
|
||||
SST_Dir_POSIX* dh;
|
||||
DIR* dirp;
|
||||
|
||||
/* Ensure no trailing slash */
|
||||
len = strlen(path);
|
||||
if(len == 0 || path[len-1] == '/')
|
||||
return NULL;
|
||||
|
||||
/* Out of memory? */
|
||||
canonPath = (char*)malloc(PATH_MAX);
|
||||
if(!canonPath)
|
||||
return NULL;
|
||||
|
||||
/* Allocate directory handle */
|
||||
dh = (SST_Dir_POSIX*)malloc(sizeof(SST_Dir_POSIX));
|
||||
if(!dh)
|
||||
{
|
||||
free(canonPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove garbage "." and ".." from path, get canonical form */
|
||||
if(!realpath(path, canonPath))
|
||||
{
|
||||
free(canonPath);
|
||||
free(dh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempt to open directory */
|
||||
dirp = opendir(canonPath);
|
||||
if(!dirp)
|
||||
{
|
||||
free(canonPath);
|
||||
free(dh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dh->canonPathLen = strlen(canonPath);
|
||||
dh->canonPath = canonPath;
|
||||
dh->dirp = dirp;
|
||||
|
||||
return (SST_Dir)dh;
|
||||
}
|
||||
|
||||
int SST_OS_ReadNextDirectoryEntry(SST_Dir dir, SST_FileInfo* fileInfoReturn)
|
||||
{
|
||||
SST_Dir_POSIX* dh = (SST_Dir_POSIX*)dir;
|
||||
struct dirent* ent;
|
||||
size_t len;
|
||||
char* tmp;
|
||||
struct stat statbuf;
|
||||
|
||||
/* Read next directory entry */
|
||||
ent = readdir(dh->dirp);
|
||||
if(!ent)
|
||||
return 0;
|
||||
|
||||
/* Ignore "." and ".." */
|
||||
if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
|
||||
return SST_OS_ReadNextDirectoryEntry(dir, fileInfoReturn);
|
||||
|
||||
len = strlen(ent->d_name);
|
||||
if(len >= SST_FILENAME_MAX)
|
||||
len = SST_FILENAME_MAX-1;
|
||||
|
||||
memcpy(fileInfoReturn->name, ent->d_name, len);
|
||||
fileInfoReturn->name[len] = 0;
|
||||
fileInfoReturn->nameLen = len;
|
||||
|
||||
tmp = (char*)alloca(dh->canonPathLen + len + 2); /* +2 because of "/" character and NULL */
|
||||
|
||||
/* Construct `canonPath` + '/' + `ent->d_name` + '\0' */
|
||||
memcpy(tmp, dh->canonPath, dh->canonPathLen);
|
||||
tmp[dh->canonPathLen] = '/';
|
||||
memcpy(&tmp[dh->canonPathLen+1], ent->d_name, len);
|
||||
tmp[dh->canonPathLen+1+len] = '\0';
|
||||
|
||||
if(stat(tmp, &statbuf) == 0)
|
||||
{
|
||||
|
||||
/* Save result */
|
||||
fileInfoReturn->isDir = S_ISDIR(statbuf.st_mode);
|
||||
fileInfoReturn->size = (fileInfoReturn->isDir ? 0 : (size_t)statbuf.st_size);
|
||||
}
|
||||
else /* can't stat() file, so not really much to say about it */
|
||||
{
|
||||
fileInfoReturn->isDir = 0;
|
||||
fileInfoReturn->size = 0;
|
||||
}
|
||||
|
||||
return (ent != NULL);
|
||||
}
|
||||
|
||||
|
||||
void SST_OS_CloseDirectory(SST_Dir dir)
|
||||
{
|
||||
SST_Dir_POSIX* dh = (SST_Dir_POSIX*)dir;
|
||||
closedir(dh->dirp);
|
||||
free(dh->canonPath);
|
||||
free(dh);
|
||||
}
|
||||
|
||||
int SST_OS_CreateDirectory(const char* dir)
|
||||
{
|
||||
/* Make a directory for anyone to read/write. */
|
||||
if(mkdir(dir, 0777) == 0)
|
||||
return 0; /* Success */
|
||||
|
||||
if(errno == EEXIST)
|
||||
{
|
||||
/* This could refer to a file by the same name, so check to
|
||||
see if it is really a directory. */
|
||||
struct stat statbuf;
|
||||
|
||||
if(stat(dir, &statbuf) == 0)
|
||||
{
|
||||
/* It really is a directory. Return positive to signal
|
||||
that the directory already exists. */
|
||||
if(S_ISDIR(statbuf.st_mode))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Other error -> failure */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_RemoveDirectory(const char* dir)
|
||||
{
|
||||
return (rmdir(dir) == 0);
|
||||
}
|
||||
|
||||
164
libsst-os/SST_FileSys_Win32.c
Normal file
164
libsst-os/SST_FileSys_Win32.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
SST_FileSys_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 3/29/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os file system querying for Win32
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_FileSys.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct SST_Dir_Win32
|
||||
{
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATAA data;
|
||||
int once;
|
||||
} SST_Dir_Win32;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Copy data from WIN32_FILE_DATAA structure to SST_FileInfo structure */
|
||||
static void copyWin32FindData(SST_FileInfo* info, const WIN32_FIND_DATAA* data)
|
||||
{
|
||||
size_t len = strlen(data->cFileName);
|
||||
|
||||
if(len >= SST_FILENAME_MAX)
|
||||
len = SST_FILENAME_MAX-1;
|
||||
|
||||
memcpy(info->name, data->cFileName, len);
|
||||
info->name[len] = '\0';
|
||||
info->size = (((uint64_t)data->nFileSizeHigh) << (8*sizeof(uint32_t))) | ((uint64_t)data->nFileSizeLow);
|
||||
info->nameLen = len;
|
||||
info->isDir = (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_Dir SST_OS_OpenDirectory(const char* path)
|
||||
{
|
||||
char findPath[MAX_PATH];
|
||||
size_t len = strlen(path);
|
||||
SST_Dir_Win32* win32dir;
|
||||
|
||||
/* Don't allow paths to end with a trailing slash */
|
||||
if(path[len-1] == '/' || path[len-1] == '\\')
|
||||
return NULL;
|
||||
|
||||
if(len > MAX_PATH-3)
|
||||
len = MAX_PATH-3;
|
||||
|
||||
/* Append "/" and "*" to the end */
|
||||
memcpy(findPath, path, len);
|
||||
findPath[len] = '/';
|
||||
findPath[len+1] = '*';
|
||||
findPath[len+2] = '\0';
|
||||
|
||||
/* Allocate structure to use */
|
||||
win32dir = (SST_Dir_Win32*)HeapAlloc(GetProcessHeap(), 0, sizeof(SST_Dir_Win32));
|
||||
if(win32dir == NULL)
|
||||
return (SST_Dir)NULL;
|
||||
|
||||
/* Attempt to find the first file */
|
||||
win32dir->hFind = FindFirstFileA(findPath, &win32dir->data);
|
||||
win32dir->once = 1;
|
||||
|
||||
/* Failed? */
|
||||
if(win32dir->hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* FindFirstFile() returns ERROR_FILE_NOT_FOUND when no files are found.
|
||||
If we didn't get that, then return NULL */
|
||||
if(GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, (void*)win32dir);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (SST_Dir)win32dir;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_ReadNextDirectoryEntry(SST_Dir dir, SST_FileInfo* fileInfoReturn)
|
||||
{
|
||||
SST_Dir_Win32* win32dir = (SST_Dir_Win32*)dir;
|
||||
int result = 0;
|
||||
|
||||
/* Check if call to FindFirstFileA() returned 0 files found */
|
||||
if(win32dir->hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* FindFirstFileA() copies the first file data automatically, so use the first time */
|
||||
if(win32dir->once)
|
||||
{
|
||||
/* NOTE: data already copied to win32dir->data when FindFirstFileA() was called */
|
||||
win32dir->once = 0;
|
||||
result = 1;
|
||||
}
|
||||
else
|
||||
result = FindNextFileA(win32dir->hFind, &win32dir->data);
|
||||
|
||||
/* If we have file data to copy, then do so now */
|
||||
if(result)
|
||||
{
|
||||
if(strcmp(win32dir->data.cFileName, ".") == 0 || strcmp(win32dir->data.cFileName, "..") == 0)
|
||||
return SST_OS_ReadNextDirectoryEntry(dir, fileInfoReturn);
|
||||
else
|
||||
copyWin32FindData(fileInfoReturn, &win32dir->data);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_CloseDirectory(SST_Dir dir)
|
||||
{
|
||||
SST_Dir_Win32* win32dir = (SST_Dir_Win32*)dir;
|
||||
|
||||
/* Close the handle if not invalid */
|
||||
if(win32dir->hFind != INVALID_HANDLE_VALUE)
|
||||
FindClose(win32dir->hFind);
|
||||
|
||||
/* Return heap memory */
|
||||
HeapFree(GetProcessHeap(), 0, (void*)win32dir);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_CreateDirectory(const char* dir)
|
||||
{
|
||||
if(CreateDirectoryA(dir, NULL) == FALSE)
|
||||
{
|
||||
if(GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
return 1; /* positive == already exists */
|
||||
else
|
||||
return -1; /* negative == error */
|
||||
}
|
||||
|
||||
return 0; /* zero == success */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_RemoveDirectory(const char* dir)
|
||||
{
|
||||
return (int)RemoveDirectory(dir);
|
||||
}
|
||||
|
||||
350
libsst-os/SST_File_POSIX.c
Normal file
350
libsst-os/SST_File_POSIX.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
SST_File_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os file I/O for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "POSIXPrivate.h"
|
||||
#include <SST/SST_File.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_File SST_OS_OpenFile(const char* path, uint32_t mode)
|
||||
{
|
||||
int flags;
|
||||
int fd;
|
||||
SST_File_POSIX* file;
|
||||
mode_t openMode = 0;
|
||||
|
||||
SST_OS_DebugAssert(path != NULL, "File path may not be NULL");
|
||||
|
||||
/* Async I/O is not yet suppported */
|
||||
if(mode & SST_OPEN_ASYNC)
|
||||
return NULL;
|
||||
|
||||
/* Only one of SST_OPEN_HINTRAND or SST_OPEN_HINTSEQ may be set. */
|
||||
if((mode & (SST_OPEN_HINTRAND|SST_OPEN_HINTSEQ)) == (SST_OPEN_HINTRAND|SST_OPEN_HINTSEQ))
|
||||
return NULL;
|
||||
|
||||
switch(mode & 0xF) /* Lower byte has the open mode, remaining 24 bits are flags */
|
||||
{
|
||||
/* In each of the three cases (r/w/a), we set the execute bit so that memory mapped
|
||||
I/O can specify 'execute' a permission too -- apparently the mapped view must be a
|
||||
subset of the permissions the file was originally opened with. */
|
||||
case SST_OPEN_READ:
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
|
||||
case SST_OPEN_WRITE:
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
openMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; /* User/Group: RW, Other: R */
|
||||
break;
|
||||
|
||||
case SST_OPEN_APPEND:
|
||||
flags = O_WRONLY | O_APPEND;
|
||||
break;
|
||||
|
||||
/* Invalid open mode */
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = open(path, flags, openMode);
|
||||
if(fd < 0)
|
||||
return NULL;
|
||||
#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L
|
||||
if(mode & SST_OPEN_HINTRAND)
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
|
||||
else if(mode & SST_OPEN_HINTSEQ)
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
file = (SST_File_POSIX*)malloc(sizeof(SST_File_POSIX));
|
||||
if(file == NULL)
|
||||
{
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file->fd = fd;
|
||||
file->isAsync = (int)(mode & SST_OPEN_ASYNC); /* Not yet used */
|
||||
#ifdef _DEBUG
|
||||
file->nrMmaps = 0;
|
||||
#endif
|
||||
|
||||
return (SST_File)file;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_WriteFile(SST_File file, const void* buf, uint64_t bytes)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
uint64_t bytesLeft = bytes;
|
||||
uint64_t totalWritten;
|
||||
const char* writePtr = (const char*)buf;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(buf != NULL, "Buffer may not be NULL");
|
||||
SST_OS_DebugAssert(!fp->isAsync, "Files opened for asynchronous I/O may not use the synchronous file I/O functions");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
/* Do nothing? */
|
||||
if(bytes == 0)
|
||||
return 0;
|
||||
|
||||
totalWritten = 0;
|
||||
do
|
||||
{
|
||||
size_t nrBytesToWrite;
|
||||
ssize_t nrWritten;
|
||||
|
||||
/* Determine how many bytes to write */
|
||||
if(bytesLeft > SIZE_MAX)
|
||||
nrBytesToWrite = SIZE_MAX;
|
||||
else
|
||||
nrBytesToWrite = (size_t)bytesLeft;
|
||||
|
||||
/* Actually write data to the file */
|
||||
nrWritten = write(fp->fd, writePtr, nrBytesToWrite);
|
||||
|
||||
if(nrWritten < 0) /* error */
|
||||
{
|
||||
/* OK, but some of the data may have been written, so stop now but return how far we did get */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advance pointers and counters */
|
||||
writePtr += nrWritten;
|
||||
totalWritten += (uint64_t)nrWritten;
|
||||
bytesLeft -= (uint64_t)nrWritten;
|
||||
} while(bytesLeft > 0);
|
||||
|
||||
return totalWritten;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_ReadFile(SST_File file, void* buf, uint64_t bytes)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
uint64_t bytesLeft = bytes;
|
||||
uint64_t totalRead;
|
||||
char* readPtr = (char*)buf;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(buf != NULL, "Buffer may not be NULL");
|
||||
SST_OS_DebugAssert(!fp->isAsync, "Files opened for asynchronous I/O may not use the synchronous file I/O functions");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Do nothing? */
|
||||
if(bytes == 0)
|
||||
return 0;
|
||||
|
||||
totalRead = 0;
|
||||
do
|
||||
{
|
||||
size_t nrBytesToRead;
|
||||
ssize_t nrRead;
|
||||
|
||||
/* Determine how many bytes to read */
|
||||
if(bytesLeft > SIZE_MAX)
|
||||
nrBytesToRead = SIZE_MAX;
|
||||
else
|
||||
nrBytesToRead = (size_t)bytesLeft;
|
||||
|
||||
|
||||
nrRead = read(fp->fd, readPtr, nrBytesToRead);
|
||||
if(nrRead <= 0)
|
||||
{
|
||||
/* Error or EOF, but some of the reads could have succeeded, so return how much
|
||||
was read */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advance pointers and counters */
|
||||
readPtr += nrRead;
|
||||
totalRead += (uint64_t)nrRead;
|
||||
bytesLeft -= (uint64_t)nrRead;
|
||||
|
||||
} while(bytesLeft > 0);
|
||||
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int SST_OS_GetFilePointer(SST_File file, uint64_t* fpReturn)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
off_t off;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(fpReturn != NULL, "File pointer return may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
off = lseek(fp->fd, 0, SEEK_CUR);
|
||||
|
||||
if(off == (off_t)-1)
|
||||
return 0;
|
||||
|
||||
*fpReturn = (uint64_t)off;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_SetFilePointer(SST_File file, uint64_t ptr)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
off_t off;
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Trying to seek > 4GB but underlying OS doesn't support it -> error */
|
||||
if(sizeof(off_t) == sizeof(uint32_t) && ptr > UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
off = (off_t)ptr;
|
||||
|
||||
if(lseek(fp->fd, off, SEEK_SET) != (off_t)-1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_FileEOF(SST_File file)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
off_t here, eof;
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Step 1: Get current file position */
|
||||
here = lseek(fp->fd, 0, SEEK_CUR);
|
||||
if(here == (off_t)-1)
|
||||
return -1;
|
||||
|
||||
/* Step 2: Seek to EOF */
|
||||
eof = lseek(fp->fd, 0, SEEK_END);
|
||||
if(eof == (off_t)-1)
|
||||
return -2;
|
||||
|
||||
/* Step 3: Put it back! */
|
||||
lseek(fp->fd, here, SEEK_SET);
|
||||
|
||||
/* Step 4: Compare and return */
|
||||
return (here == eof);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_FlushFile(SST_File file)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
|
||||
(void)fsync(fp->fd);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_CloseFile(SST_File file)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
|
||||
if(fp->fd > 0)
|
||||
{
|
||||
close(fp->fd);
|
||||
#ifdef _DEBUG
|
||||
fp->fd = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Closing file with open memory maps means leaked OS resources");
|
||||
#endif
|
||||
|
||||
free(fp);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_SeekFile(SST_File file, int64_t offset, int fromWhere)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
int method;
|
||||
off_t off;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
off = (off_t)offset;
|
||||
|
||||
/* Map SST to POSIX constants (pretty sure they are isomorphic) */
|
||||
switch(fromWhere)
|
||||
{
|
||||
case SST_SEEK_START: method = SEEK_SET; break;
|
||||
case SST_SEEK_CUR: method = SEEK_CUR; break;
|
||||
case SST_SEEK_END: method = SEEK_END; break;
|
||||
|
||||
/* Invalid parameter */
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
if(lseek(fp->fd, off, method) == (off_t)-1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetFileSize(SST_File file)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
struct stat info;
|
||||
|
||||
if(fstat(fp->fd, &info) == 0) /* i.e. success */
|
||||
return (uint64_t)info.st_size;
|
||||
|
||||
/* Failure */
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
370
libsst-os/SST_File_Win32.c
Normal file
370
libsst-os/SST_File_Win32.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
SST_File_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os file I/O for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <SST/SST_File.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_File SST_OS_OpenFile(const char* path, uint32_t mode)
|
||||
{
|
||||
DWORD accessFlags;
|
||||
DWORD createFlags;
|
||||
DWORD otherFlags;
|
||||
DWORD shareFlags;
|
||||
HANDLE hFile;
|
||||
SST_File_Win32* file;
|
||||
|
||||
SST_OS_DebugAssert(path != NULL, "File path may not be NULL");
|
||||
|
||||
/* Async I/O is not yet suppported */
|
||||
/* see win32 flag FILE_FLAG_OVERLAPPED */
|
||||
if(mode & SST_OPEN_ASYNC)
|
||||
return NULL;
|
||||
|
||||
/* Only one of SST_OPEN_HINTRAND or SST_OPEN_HINTSEQ may be set. */
|
||||
if((mode & (SST_OPEN_HINTRAND|SST_OPEN_HINTSEQ)) == (SST_OPEN_HINTRAND|SST_OPEN_HINTSEQ))
|
||||
return NULL;
|
||||
|
||||
otherFlags = FILE_ATTRIBUTE_NORMAL;
|
||||
switch(mode & 0xF) /* Lower byte has the open mode, remaining 24 bits are flags */
|
||||
{
|
||||
/* In each of the three cases (r/w/a), we set the execute bit so that memory mapped
|
||||
I/O can specify 'execute' a permission too -- apparently the mapped view must be a
|
||||
subset of the permissions the file was originally opened with. */
|
||||
case SST_OPEN_READ:
|
||||
createFlags = OPEN_EXISTING;
|
||||
accessFlags = GENERIC_READ | GENERIC_EXECUTE;
|
||||
shareFlags = FILE_SHARE_READ;
|
||||
break;
|
||||
|
||||
case SST_OPEN_WRITE:
|
||||
createFlags = CREATE_ALWAYS;
|
||||
accessFlags = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE;
|
||||
shareFlags = 0;
|
||||
break;
|
||||
|
||||
case SST_OPEN_APPEND:
|
||||
createFlags = OPEN_ALWAYS;
|
||||
accessFlags = FILE_APPEND_DATA;
|
||||
shareFlags = 0;
|
||||
break;
|
||||
|
||||
/* Invalid open mode */
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mode & SST_OPEN_HINTRAND)
|
||||
otherFlags |= FILE_FLAG_RANDOM_ACCESS;
|
||||
else if(mode & SST_OPEN_HINTSEQ)
|
||||
otherFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
|
||||
|
||||
hFile = CreateFileA(path, accessFlags, shareFlags, NULL, createFlags, otherFlags, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
/* Append mode: start at end of file */
|
||||
if((mode & 0xF) == SST_OPEN_APPEND)
|
||||
SetFilePointer(hFile, 0, NULL, FILE_END);
|
||||
|
||||
/* Can't use malloc(), so use the process heap */
|
||||
file = (SST_File_Win32*)HeapAlloc(GetProcessHeap(), 0, sizeof(SST_File_Win32));
|
||||
if(file == NULL)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file->hFile = hFile;
|
||||
file->hMap = NULL;
|
||||
file->isAsync = (int)(mode & SST_OPEN_ASYNC); /* Not yet used */
|
||||
file->accessFlags = accessFlags;
|
||||
#ifdef _DEBUG
|
||||
file->nrMmaps = 0;
|
||||
#endif
|
||||
|
||||
return (SST_File)file;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_OS_WriteFile(SST_File file, const void* buf, uint64_t bytes)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
uint64_t bytesLeft = bytes;
|
||||
uint64_t totalWritten;
|
||||
const char* writePtr = (const char*)buf;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(buf != NULL, "Buffer may not be NULL");
|
||||
SST_OS_DebugAssert(!fp->isAsync, "Files opened for asynchronous I/O may not use the synchronous file I/O functions");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
/* Do nothing? */
|
||||
if(bytes == 0)
|
||||
return 0;
|
||||
|
||||
totalWritten = 0;
|
||||
do
|
||||
{
|
||||
DWORD nrBytesToWrite, nrWritten;
|
||||
|
||||
/* Determine how many bytes to write (at most 4GB per WriteFile() call) */
|
||||
if(bytesLeft > (uint64_t)0xFFFFFFFF)
|
||||
nrBytesToWrite = 0xFFFFFFFF;
|
||||
else
|
||||
nrBytesToWrite = (DWORD)bytesLeft;
|
||||
|
||||
/* Ensure invalid 'nrWritten' before calling WriteFile() */
|
||||
nrWritten = 0;
|
||||
|
||||
/* Actually write data to the file */
|
||||
if(WriteFile(fp->hFile, writePtr, nrBytesToWrite, &nrWritten, NULL) == FALSE)
|
||||
{
|
||||
/* OK, but some of the data may have been written, so stop now but return how far we did get */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advance pointers and counters */
|
||||
writePtr += nrWritten;
|
||||
totalWritten += (uint64_t)nrWritten;
|
||||
bytesLeft -= (uint64_t)nrWritten;
|
||||
} while(bytesLeft > 0);
|
||||
|
||||
return totalWritten;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_OS_ReadFile(SST_File file, void* buf, uint64_t bytes)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
uint64_t bytesLeft = bytes;
|
||||
uint64_t totalRead;
|
||||
char* readPtr = (char*)buf;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(buf != NULL, "Buffer may not be NULL");
|
||||
SST_OS_DebugAssert(!fp->isAsync, "Files opened for asynchronous I/O may not use the synchronous file I/O functions");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
/* Do nothing? */
|
||||
if(bytes == 0)
|
||||
return 0;
|
||||
|
||||
totalRead = 0;
|
||||
do
|
||||
{
|
||||
DWORD nrBytesToRead, nrRead;
|
||||
|
||||
/* Determine how many bytes to read (at most 4GB per ReadFile() call) */
|
||||
if(bytesLeft > (uint64_t)0xFFFFFFFF)
|
||||
nrBytesToRead = 0xFFFFFFFF;
|
||||
else
|
||||
nrBytesToRead = (DWORD)bytesLeft;
|
||||
|
||||
/* Ensure invalid 'nrRead' before calling ReadFile() */
|
||||
nrRead = 0;
|
||||
|
||||
if(ReadFile(fp->hFile, readPtr, nrBytesToRead, &nrRead, NULL) == FALSE)
|
||||
{
|
||||
/* Error, but some of the reads could have succeeded, so return how much
|
||||
was read */
|
||||
break;
|
||||
}
|
||||
|
||||
/* When nrRead is 0 but ReadFile() returns true, then the EOF is hit */
|
||||
if(nrRead == 0)
|
||||
break;
|
||||
|
||||
/* Advance pointers and counters */
|
||||
readPtr += (size_t)nrRead;
|
||||
totalRead += (uint64_t)nrRead;
|
||||
bytesLeft -= (uint64_t)nrRead;
|
||||
} while(bytesLeft > 0);
|
||||
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_GetFilePointer(SST_File file, uint64_t* fpReturn)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
LARGE_INTEGER zeroPos, newPos;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert(fpReturn != NULL, "File pointer return may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Zero bytes from 'current' = just get the position */
|
||||
zeroPos.QuadPart = 0;
|
||||
|
||||
if(SetFilePointerEx(fp->hFile, zeroPos, &newPos, FILE_CURRENT) == FALSE)
|
||||
return 0;
|
||||
|
||||
*fpReturn = (uint64_t)newPos.QuadPart;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_SetFilePointer(SST_File file, uint64_t ptr)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
LARGE_INTEGER pos;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Set it */
|
||||
pos.QuadPart = (LONGLONG)ptr;
|
||||
if(SetFilePointerEx(fp->hFile, pos, NULL, FILE_BEGIN) == FALSE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_FileEOF(SST_File file)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
LARGE_INTEGER ptr, end, zero;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
zero.QuadPart = 0;
|
||||
|
||||
/* Step 1: Get current file position */
|
||||
if(SetFilePointerEx(fp->hFile, zero, &ptr, FILE_CURRENT) == FALSE)
|
||||
return -2;
|
||||
|
||||
/* Step 2: Get end of file position */
|
||||
if(GetFileSizeEx(fp->hFile, &end) == FALSE)
|
||||
return -3;
|
||||
|
||||
/* Step 3: Compare */
|
||||
return (ptr.QuadPart == end.QuadPart);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_FlushFile(SST_File file)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
|
||||
(void)FlushFileBuffers(fp->hFile);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_CloseFile(SST_File file)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
|
||||
if(fp->hFile != NULL)
|
||||
{
|
||||
CloseHandle(fp->hFile);
|
||||
#ifdef _DEBUG
|
||||
fp->hFile = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(fp->hMap != NULL)
|
||||
{
|
||||
CloseHandle(fp->hMap);
|
||||
#ifdef _DEBUG
|
||||
fp->hMap = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Closing file with open memory maps means leaked OS resources");
|
||||
#endif
|
||||
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, fp);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_SeekFile(SST_File file, int64_t offset, int fromWhere)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
LARGE_INTEGER pos;
|
||||
DWORD method;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
#ifdef _DEBUG
|
||||
SST_OS_DebugAssert(fp->nrMmaps == 0, "Cannot use synchronous file I/O while memory maps exist!");
|
||||
#endif
|
||||
|
||||
/* Map SST to Win32 constants (pretty sure they are isomorphic) */
|
||||
switch(fromWhere)
|
||||
{
|
||||
case SST_SEEK_START: method = FILE_BEGIN; break;
|
||||
case SST_SEEK_CUR: method = FILE_CURRENT; break;
|
||||
case SST_SEEK_END: method = FILE_END; break;
|
||||
|
||||
/* Invalid parameter */
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
/* Save the offset, then do it */
|
||||
pos.QuadPart = (LONGLONG)offset;
|
||||
if(SetFilePointerEx(fp->hFile, pos, NULL, method) == FALSE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetFileSize(SST_File file)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
LARGE_INTEGER size;
|
||||
|
||||
if(GetFileSizeEx(fp->hFile, &size))
|
||||
return (uint64_t)size.QuadPart;
|
||||
|
||||
/* Failure */
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
170
libsst-os/SST_Mmap_POSIX.c
Normal file
170
libsst-os/SST_Mmap_POSIX.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
SST_Mmap_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os memory mapped file I/O functions for POSIX
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "POSIXPrivate.h"
|
||||
#include <sys/stat.h>
|
||||
#include <SST/SST_Mmap.h>
|
||||
#include <SST/SST_SysMem.h> /* SST_PROTECT_XXXXX constants, SST_OS_GetPageSize() */
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
void __libsst_init_mmapsize() { /* Not used on POSIX */ }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32_t SST_OS_GetMmapGranularity(void)
|
||||
{
|
||||
return SST_OS_GetPageSize();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_MemoryMap SST_OS_CreateMmap(SST_File file, uint64_t offset, size_t mapLength, int mode)
|
||||
{
|
||||
SST_File_POSIX* fp = (SST_File_POSIX*)file;
|
||||
SST_MemoryMap_POSIX* mm;
|
||||
int access = 0;
|
||||
void* ptr;
|
||||
off_t off;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert((mode & (~(SST_PROTECT_READ|SST_PROTECT_WRITE|SST_PROTECT_EXEC))) == 0, "The mode bits may only contain SST_PROTECT_READ/WRITE/EXEC and nothing else");
|
||||
SST_OS_DebugAssert((offset & (SST_OS_GetMmapGranularity()-1)) == 0, "Offset must be aligned to system granularity. Use SST_OS_GetMmapGranuality() to determine this");
|
||||
SST_OS_DebugAssert( (offset == 0 && mapLength == 0) || mapLength > 0, "Map length must be non-zero OR offset and length must both be zero (map whole file)");
|
||||
|
||||
if(mode & SST_PROTECT_READ)
|
||||
access |= PROT_READ;;
|
||||
if(mode & SST_PROTECT_WRITE)
|
||||
access |= PROT_WRITE;
|
||||
if(mode & SST_PROTECT_EXEC)
|
||||
access |= PROT_EXEC;
|
||||
|
||||
off = (off_t)offset;
|
||||
|
||||
/* Map whole file */
|
||||
if(mapLength == 0)
|
||||
{
|
||||
struct stat s;
|
||||
if(fstat(fp->fd, &s) == 0)
|
||||
mapLength = (size_t)s.st_size;
|
||||
else /* fstat() failed, try lseek() */
|
||||
{
|
||||
off_t here, end;
|
||||
|
||||
here = lseek(fp->fd, 0, SEEK_CUR);
|
||||
end = lseek(fp->fd, 0, SEEK_END);
|
||||
|
||||
/* failed? */
|
||||
if(here == (off_t)-1 || end == (off_t)-1)
|
||||
return NULL;
|
||||
|
||||
mapLength = (size_t)end;
|
||||
|
||||
/* Restore file position (not that it matters much if you mmap() the whole thing) */
|
||||
lseek(fp->fd, here, SEEK_SET);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ptr = mmap(NULL, mapLength, access, MAP_SHARED, fp->fd, off);
|
||||
|
||||
if(ptr == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
/* Allocate a memory map region */
|
||||
mm = (SST_MemoryMap_POSIX*)malloc(sizeof(SST_MemoryMap_POSIX));
|
||||
if(mm == NULL)
|
||||
{
|
||||
munmap(ptr, mapLength);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mm->offset = offset;
|
||||
mm->len = mapLength;
|
||||
mm->base = ptr;
|
||||
#ifdef _DEBUG
|
||||
mm->owner = fp;
|
||||
fp->nrMmaps++;
|
||||
#endif
|
||||
|
||||
return (SST_MemoryMap)mm;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_DestroyMmap(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_POSIX* mm = (SST_MemoryMap_POSIX*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
munmap(mm->base, mm->len);
|
||||
|
||||
#ifdef _DEBUG
|
||||
mm->base = NULL;
|
||||
mm->owner->nrMmaps--;
|
||||
#endif
|
||||
|
||||
free(mm);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void* SST_OS_GetMmapBase(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_POSIX* mm = (SST_MemoryMap_POSIX*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->base;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
size_t SST_OS_GetMmapSize(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_POSIX* mm = (SST_MemoryMap_POSIX*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMmapOffset(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_POSIX* mm = (SST_MemoryMap_POSIX*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->offset;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_OS_SyncMmap(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_POSIX* mm = (SST_MemoryMap_POSIX*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
/* Synchronize with the OS, but do so async */
|
||||
msync(mm->base, mm->len, MS_ASYNC);
|
||||
}
|
||||
|
||||
188
libsst-os/SST_Mmap_Win32.c
Normal file
188
libsst-os/SST_Mmap_Win32.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
SST_Mmap_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os memory mapped file I/O functions for Win32 systems (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <SST/SST_Mmap.h>
|
||||
#include <SST/SST_SysMem.h> /* SST_PROTECT_XXXXX constants */
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#if !defined(FILE_MAP_EXECUTE) /* Added in Windows XP SP2 */
|
||||
#define FILE_MAP_EXECUTE 0x20
|
||||
#endif
|
||||
|
||||
static uint32_t allocGranularity;
|
||||
|
||||
void __libsst_init_mmapsize()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
|
||||
GetNativeSystemInfo(&si);
|
||||
|
||||
allocGranularity = (uint32_t)si.dwAllocationGranularity;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t SST_OS_GetMmapGranularity(void)
|
||||
{
|
||||
return allocGranularity;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_MemoryMap SST_OS_CreateMmap(SST_File file, uint64_t offset, size_t mapLength, int mode)
|
||||
{
|
||||
SST_File_Win32* fp = (SST_File_Win32*)file;
|
||||
SST_MemoryMap_Win32* mm;
|
||||
DWORD access, offsetLow, offsetHigh;
|
||||
void* ptr;
|
||||
|
||||
SST_OS_DebugAssert(file != NULL, "File handle may not be NULL");
|
||||
SST_OS_DebugAssert((mode & (~(SST_PROTECT_READ|SST_PROTECT_WRITE|SST_PROTECT_EXEC))) == 0, "The mode bits may only contain SST_PROTECT_READ/WRITE/EXEC and nothing else");
|
||||
SST_OS_DebugAssert((offset & (SST_OS_GetMmapGranularity()-1)) == 0, "Offset must be aligned to system granularity. Use SST_OS_GetMmapGranuality() to determine this");
|
||||
SST_OS_DebugAssert((offset == 0 && mapLength == 0) || mapLength > 0, "Map length must be non-zero OR offset and length must both be zero (map whole file)");
|
||||
|
||||
/* No file mapping yet? */
|
||||
if(fp->hMap == NULL)
|
||||
{
|
||||
DWORD pageProt;
|
||||
|
||||
/* Decide on protection flags. See SST_File_Win32.c/SST_OS_OpenFile() for the 'case' values */
|
||||
switch(fp->accessFlags)
|
||||
{
|
||||
case GENERIC_READ | GENERIC_EXECUTE: pageProt = PAGE_EXECUTE_READ; break;
|
||||
case GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE: pageProt = PAGE_EXECUTE_READWRITE; break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
/* Actually create the file mapping */
|
||||
fp->hMap = CreateFileMappingA(fp->hFile, NULL, pageProt, 0, 0, NULL);
|
||||
if(fp->hMap == NULL)
|
||||
return NULL;
|
||||
}
|
||||
/* Windows is weird about its flags: it allows {R, W} + {X}, so only 4 combinations of
|
||||
possible values. However, the 'W' bit implies 'R'. */
|
||||
if(mode & SST_PROTECT_READ)
|
||||
access = FILE_MAP_READ;
|
||||
if(mode & SST_PROTECT_WRITE)
|
||||
access = FILE_MAP_WRITE; /* This is actually r/w, which is why we don't use "else if(...)" */
|
||||
if(mode & SST_PROTECT_EXEC)
|
||||
access |= FILE_MAP_EXECUTE;
|
||||
|
||||
offsetLow = (DWORD)(offset & 0xFFFFFFFF);
|
||||
offsetHigh = (DWORD)(offset >> 32);
|
||||
|
||||
/* Windows already treats a mapLength == 0 as "map to end of file". We just ensure (at the top) that
|
||||
offset == 0 so it really means "map from beginning to end". */
|
||||
|
||||
ptr = MapViewOfFileEx(fp->hMap, access, offsetHigh, offsetLow, mapLength, NULL);
|
||||
|
||||
if(ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate a memory map region */
|
||||
mm = (SST_MemoryMap_Win32*)HeapAlloc(GetProcessHeap(), 0, sizeof(SST_MemoryMap_Win32));
|
||||
if(mm == NULL)
|
||||
{
|
||||
UnmapViewOfFile(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mapLength == 0)
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
GetFileSizeEx(fp->hFile, &size);
|
||||
|
||||
mapLength = (size_t)size.QuadPart;
|
||||
}
|
||||
|
||||
mm->offset = offset;
|
||||
mm->len = mapLength;
|
||||
mm->base = ptr;
|
||||
#ifdef _DEBUG
|
||||
mm->owner = fp;
|
||||
fp->nrMmaps++;
|
||||
#endif
|
||||
|
||||
return (SST_MemoryMap)mm;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_DestroyMmap(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_Win32* mm = (SST_MemoryMap_Win32*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
UnmapViewOfFile(mm->base);
|
||||
|
||||
#ifdef _DEBUG
|
||||
mm->base = NULL;
|
||||
mm->owner->nrMmaps--;
|
||||
#endif
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, mm);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_GetMmapBase(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_Win32* mm = (SST_MemoryMap_Win32*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->base;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
size_t SST_OS_GetMmapSize(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_Win32* mm = (SST_MemoryMap_Win32*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->len;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMmapOffset(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_Win32* mm = (SST_MemoryMap_Win32*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
return mm->offset;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_OS_SyncMmap(SST_MemoryMap mappedRegion)
|
||||
{
|
||||
SST_MemoryMap_Win32* mm = (SST_MemoryMap_Win32*)mappedRegion;
|
||||
|
||||
SST_OS_DebugAssert(mappedRegion != NULL, "Memory map handle may not be NULL");
|
||||
|
||||
FlushViewOfFile(mm->base, mm->len);
|
||||
}
|
||||
|
||||
33
libsst-os/SST_OSInit.c
Normal file
33
libsst-os/SST_OSInit.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
SST_OSInit.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 5/29/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os initialization function
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
extern void __libsst_init_endian();
|
||||
extern void __libsst_init_pagesize();
|
||||
extern void __libsst_init_mmapsize();
|
||||
extern int __libsst_init_time();
|
||||
extern int __libsst_init_user();
|
||||
|
||||
int SST_OS_Init()
|
||||
{
|
||||
__libsst_init_endian();
|
||||
__libsst_init_pagesize();
|
||||
__libsst_init_mmapsize();
|
||||
|
||||
return __libsst_init_time() && __libsst_init_user();
|
||||
}
|
||||
407
libsst-os/SST_SafeArithmetic.c
Normal file
407
libsst-os/SST_SafeArithmetic.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
SST_SafeArithmetic.c
|
||||
Author: Chris Ertel <crertel@762studios.com>
|
||||
Created: 1/16/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Functions to help perform integer arithmetic while catching overflow conditions.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_SafeArithmetic.h>
|
||||
#include <limits.h>
|
||||
|
||||
int SST_OS_SafeAddI8(int8_t _a, int8_t _b, int8_t* _out)
|
||||
{
|
||||
int8_t ret = _a + _b;
|
||||
|
||||
/* if they are opposite signs, they cannot overflow */
|
||||
if ( (_a >= 0 && _b <= 0) ||
|
||||
(_b >= 0 && _a <= 0) )
|
||||
{
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if they are the same sign, check for overflow */
|
||||
if (_a < 0 || _b < 0)
|
||||
{
|
||||
if (ret > _a && ret > _b)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret < _a && ret < _b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI8ToSizeT(int8_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _size + _a;
|
||||
|
||||
if (_a >= 0)
|
||||
{
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret > _size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU8(uint8_t _a, uint8_t _b, uint8_t* _out)
|
||||
{
|
||||
uint8_t ret = _a + _b;
|
||||
|
||||
if (ret < _a || ret < _b)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeMultiplyU8(uint8_t _a, uint8_t _b, uint8_t* _out)
|
||||
{
|
||||
uint16_t a = _a;
|
||||
uint16_t b = _b;
|
||||
uint16_t ret = a*b;
|
||||
|
||||
if (ret > 0xff)
|
||||
return 0;
|
||||
|
||||
*_out = (uint8_t) ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU8ToSizeT(uint8_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _a + _size;
|
||||
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI16(int16_t _a, int16_t _b, int16_t* _out)
|
||||
{
|
||||
int16_t ret = _a + _b;
|
||||
|
||||
/* if they are opposite signs, they cannot overflow */
|
||||
if ( (_a >= 0 && _b <= 0) ||
|
||||
(_b >= 0 && _a <= 0) )
|
||||
{
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if they are the same sign, check for overflow */
|
||||
if (_a < 0 || _b < 0)
|
||||
{
|
||||
if (ret > _a && ret > _b)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret < _a && ret < _b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI16ToSizeT(int16_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _size + _a;
|
||||
|
||||
if (_a >= 0)
|
||||
{
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret > _size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU16(uint16_t _a, uint16_t _b, uint16_t* _out)
|
||||
{
|
||||
uint16_t ret = _a + _b;
|
||||
|
||||
if (ret < _a || ret < _b)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeMultiplyU16(uint16_t _a, uint16_t _b, uint16_t* _out)
|
||||
{
|
||||
uint32_t a = _a;
|
||||
uint32_t b = _b;
|
||||
uint32_t ret = a*b;
|
||||
|
||||
if (ret > 0xffff)
|
||||
return 0;
|
||||
|
||||
*_out = (uint16_t) ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU16ToSizeT(uint16_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _a + _size;
|
||||
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI32(int32_t _a, int32_t _b, int32_t* _out)
|
||||
{
|
||||
int32_t ret = _a + _b;
|
||||
|
||||
/* if they are opposite signs, they cannot overflow */
|
||||
if ( (_a >= 0 && _b <= 0) ||
|
||||
(_b >= 0 && _a <= 0) )
|
||||
{
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if they are the same sign, check for overflow */
|
||||
if (_a < 0 || _b < 0)
|
||||
{
|
||||
if (ret > _a && ret > _b)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret < _a && ret < _b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI32ToSizeT(int32_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _size + _a;
|
||||
|
||||
if (_a >= 0)
|
||||
{
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret > _size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU32(uint32_t _a, uint32_t _b, uint32_t* _out)
|
||||
{
|
||||
uint32_t ret = _a + _b;
|
||||
|
||||
if (ret < _b || ret < _a)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeMultiplyU32(uint32_t _a, uint32_t _b, uint32_t* _out)
|
||||
{
|
||||
uint64_t a = _a;
|
||||
uint64_t b = _b;
|
||||
uint64_t ret = a*b;
|
||||
|
||||
if (ret > 0xffffffff)
|
||||
return 0;
|
||||
|
||||
*_out = (uint32_t) ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU32ToSizeT(uint32_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
size_t ret = _a + _size;
|
||||
|
||||
if (ret < _size)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI64(int64_t _a, int64_t _b, int64_t* _out)
|
||||
{
|
||||
int64_t ret = _a + _b;
|
||||
|
||||
/* if they are opposite signs, they cannot overflow */
|
||||
if ( (_a >= 0 && _b <= 0) ||
|
||||
(_b >= 0 && _a <= 0) )
|
||||
{
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if they are the same sign, check for overflow */
|
||||
if (_a < 0 || _b < 0)
|
||||
{
|
||||
if (ret > _a && ret > _b)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret < _a && ret < _b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddI64ToSizeT(int64_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
|
||||
/* Positive value being added */
|
||||
if(_a >= 0)
|
||||
{
|
||||
/*
|
||||
Some weirdness with the casting: if you cast 32-bit size_t to
|
||||
a signed int64_t, it can sign extend the value. This is bad.
|
||||
We want to zero extend to 64 bits, *then* interpret that as
|
||||
a 64-bit integer. In other words, size_t -> int64_t should
|
||||
always be a positive integer, and the upper 32-bits are zero.
|
||||
|
||||
On 64-bit machines where size_t is 64 bits, then the cast
|
||||
will never do a sign extend.
|
||||
*/
|
||||
const int64_t diff64 = (int64_t)((uint64_t)(SIZE_MAX - _size));
|
||||
|
||||
/* Then it shouldn't matter */
|
||||
if(_a > diff64)
|
||||
return 0;
|
||||
}
|
||||
else /* Negative value being added. */
|
||||
{
|
||||
const int64_t size64 = (int64_t)((uint64_t)_size);
|
||||
|
||||
/* Ensure that if _a was added, the results
|
||||
would be > 0, otherwise it is negative we
|
||||
would overflow */
|
||||
if(size64 + _a < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*_out = (size_t)_a + _size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU64(uint64_t _a, uint64_t _b, uint64_t* _out)
|
||||
{
|
||||
uint64_t ret = _a + _b;
|
||||
|
||||
if (ret < _a || ret < _b)
|
||||
return 0;
|
||||
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* SLOWSLOW This is obviously correct, but not fast. Use LUTs or something. */
|
||||
static int countHighestSetBitU64(uint64_t _in)
|
||||
{
|
||||
int ret = 0;
|
||||
while (_in > 0)
|
||||
{
|
||||
_in >>= 1;
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NOTE: For explanation, see ( http://stackoverflow.com/a/199455 ). */
|
||||
int SST_OS_SafeMultiplyU64(uint64_t _a, uint64_t _b, uint64_t* _out)
|
||||
{
|
||||
uint64_t ret;
|
||||
int log2a;
|
||||
int log2b;
|
||||
|
||||
/* special-case for 1 -- probably not needed */
|
||||
if (_a == 1 || _b == 1)
|
||||
{
|
||||
*_out = _a*_b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
log2a = countHighestSetBitU64(_a);
|
||||
log2b = countHighestSetBitU64(_b);
|
||||
|
||||
if (log2a + log2b > 64)
|
||||
return 0;
|
||||
|
||||
ret = _a*_b;
|
||||
*_out = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddU64ToSizeT(uint64_t _a, size_t _size, size_t* _out)
|
||||
{
|
||||
const size_t diff = SIZE_MAX - _size;
|
||||
const uint64_t diff64 = (uint64_t)diff;
|
||||
|
||||
if(diff64 < _a)
|
||||
return 0;
|
||||
|
||||
*_out = (size_t)_a + _size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SST_OS_SafeAddSizeTToSizeT( size_t _a, size_t _b, size_t* _out)
|
||||
{
|
||||
size_t out = _a + _b;
|
||||
if (out < _a && out < _b)
|
||||
return 0;
|
||||
|
||||
*_out = out;
|
||||
return 1;
|
||||
}
|
||||
147
libsst-os/SST_SysMem_POSIX.c
Normal file
147
libsst-os/SST_SysMem_POSIX.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
SST_SysMem_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os system memory allocation functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "POSIXPrivate.h"
|
||||
#include <SST/SST_SysMem.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include<sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
static uint32_t cached_pagesize;
|
||||
|
||||
void __libsst_init_pagesize()
|
||||
{
|
||||
uint32_t pgsz = (uint32_t)-1;
|
||||
|
||||
#ifdef _SC_PAGESIZE
|
||||
pgsz = (uint32_t)sysconf(_SC_PAGESIZE);
|
||||
#elif defined(_SC_PAGE_SIZE)
|
||||
if(pgsz == (uint32_t)-1)
|
||||
pgsz = (uint32_t)sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
|
||||
cached_pagesize = pgsz;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMemorySize()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
int param[2] = { CTL_HW, HW_MEMSIZE };
|
||||
uint64_t mem;
|
||||
size_t size = sizeof(mem);
|
||||
sysctl(param, 2, &mem, &size, NULL, 0);
|
||||
return mem;
|
||||
#else
|
||||
uint32_t pagesize = SST_OS_GetPageSize();
|
||||
uint32_t pages;
|
||||
|
||||
pages = sysconf(_SC_PHYS_PAGES);
|
||||
if(pages == (uint32_t)-1)
|
||||
return 0;
|
||||
|
||||
return (uint64_t)pages*(uint64_t)pagesize;
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32_t SST_OS_GetPageSize()
|
||||
{
|
||||
return cached_pagesize;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void* SST_OS_AllocPages(size_t allocBytes)
|
||||
{
|
||||
void* addr;
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
int flags = MAP_SHARED | MAP_ANON;
|
||||
#else
|
||||
int flags = MAP_SHARED | MAP_ANONYMOUS;
|
||||
#endif
|
||||
|
||||
SST_OS_DebugAssert(allocBytes > 0, "Allocating 0 bytes is not allowed");
|
||||
|
||||
#ifdef MAP_UNINITIALIZED /* Linux only, 2.6.33+, don't zero pages */
|
||||
flags |= MAP_UNINITIALIZED;
|
||||
#endif
|
||||
|
||||
addr = mmap(NULL, allocBytes, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
|
||||
if(addr == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_FreePages(void* pageBase, size_t nrBytes)
|
||||
{
|
||||
uintptr_t addr;
|
||||
uint32_t pageSize;
|
||||
|
||||
SST_OS_DebugAssert(pageBase != NULL, "Base address may not be NULL");
|
||||
SST_OS_DebugAssert(nrBytes > 0, "The number of bytes to free may not be zero");
|
||||
|
||||
addr = (uintptr_t)pageBase;
|
||||
pageSize = SST_OS_GetPageSize();
|
||||
|
||||
/* Check if address is aligned to page boundary */
|
||||
if(addr & (pageSize-1))
|
||||
return -1;
|
||||
|
||||
/* Free the pages */
|
||||
return (munmap(pageBase, nrBytes) == 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_ProtectPages(void* pageBase, size_t nrBytes, int protectFlags)
|
||||
{
|
||||
uintptr_t addr;
|
||||
uint32_t pageSize;
|
||||
int newFlags = 0;
|
||||
|
||||
SST_OS_DebugAssert(pageBase != NULL, "Base address may not be NULL");
|
||||
SST_OS_DebugAssert(nrBytes > 0, "The number of bytes to free may not be zero");
|
||||
SST_OS_DebugAssert((protectFlags & (~(SST_PROTECT_READ|SST_PROTECT_WRITE|SST_PROTECT_EXEC))) == 0, "Protect flags contain invalid bits");
|
||||
|
||||
addr = (uintptr_t)pageBase;
|
||||
pageSize = SST_OS_GetPageSize();
|
||||
|
||||
/* Check if address is aligned to page boundary */
|
||||
if(addr & (pageSize-1))
|
||||
return -1;
|
||||
|
||||
if(protectFlags & SST_PROTECT_READ)
|
||||
newFlags |= PROT_READ;
|
||||
if(protectFlags & SST_PROTECT_WRITE)
|
||||
newFlags |= PROT_WRITE;
|
||||
if(protectFlags & SST_PROTECT_EXEC)
|
||||
newFlags |= PROT_EXEC;
|
||||
|
||||
return (mprotect(pageBase, nrBytes, newFlags) == 0);
|
||||
}
|
||||
|
||||
155
libsst-os/SST_SysMem_Win32.c
Normal file
155
libsst-os/SST_SysMem_Win32.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
SST_SysMem_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os system memory allocation functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <SST/SST_SysMem.h>
|
||||
#include <SST/SST_Assert.h>
|
||||
|
||||
static uint32_t cached_pagesize;
|
||||
|
||||
void __libsst_init_pagesize()
|
||||
{
|
||||
SYSTEM_INFO info;
|
||||
GetNativeSystemInfo(&info);
|
||||
|
||||
cached_pagesize = (uint32_t)info.dwPageSize;
|
||||
}
|
||||
|
||||
/* Round an allocation of 'amount' bytes to be a multiple of 'pageSize' */
|
||||
static size_t roundToPage(uint32_t pageSize, size_t amount)
|
||||
{
|
||||
size_t rounded;
|
||||
|
||||
/* ASSUMPTION: pageSize is a power of two */
|
||||
|
||||
/*
|
||||
Algorithm: Round up allocation to the nearest page.
|
||||
|
||||
[1] x & (pageSize-1) = Bytes that are extra parts of a page
|
||||
[2] x & (~(pageSize-1)) = Bytes that are whole pages.
|
||||
|
||||
Start with [2] bytes. If [1] is non-zero, then add page size.
|
||||
*/
|
||||
rounded = amount & (~(pageSize-1));
|
||||
if(amount & (pageSize-1))
|
||||
rounded += pageSize;
|
||||
|
||||
return rounded;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMemorySize()
|
||||
{
|
||||
ULONGLONG mem = 0;
|
||||
|
||||
if(GetPhysicallyInstalledSystemMemory(&mem))
|
||||
return (uint64_t)mem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t SST_OS_GetPageSize()
|
||||
{
|
||||
return cached_pagesize;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_OS_AllocPages(size_t allocBytes)
|
||||
{
|
||||
SST_OS_DebugAssert(allocBytes > 0, "Allocating 0 bytes is not allowed");
|
||||
|
||||
return VirtualAllocEx(GetCurrentProcess(), NULL, roundToPage(SST_OS_GetPageSize(), allocBytes), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_FreePages(void* pageBase, size_t nrBytes)
|
||||
{
|
||||
uintptr_t addr;
|
||||
uint32_t pageSize;
|
||||
|
||||
SST_OS_DebugAssert(pageBase != NULL, "Base address may not be NULL");
|
||||
SST_OS_DebugAssert(nrBytes > 0, "The number of bytes to free may not be zero");
|
||||
|
||||
addr = (uintptr_t)pageBase;
|
||||
pageSize = SST_OS_GetPageSize();
|
||||
|
||||
/* Check if address is aligned to page boundary */
|
||||
if(addr & (pageSize-1))
|
||||
return -1;
|
||||
|
||||
/* Free the pages */
|
||||
if(VirtualFreeEx(GetCurrentProcess(), pageBase, roundToPage(pageSize, nrBytes), MEM_DECOMMIT | MEM_RELEASE) != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_OS_ProtectPages(void* pageBase, size_t nrBytes, int protectFlags)
|
||||
{
|
||||
uintptr_t addr;
|
||||
uint32_t pageSize;
|
||||
DWORD newFlags = PAGE_NOACCESS;
|
||||
|
||||
SST_OS_DebugAssert(pageBase != NULL, "Base address may not be NULL");
|
||||
SST_OS_DebugAssert(nrBytes > 0, "The number of bytes to free may not be zero");
|
||||
|
||||
|
||||
addr = (uintptr_t)pageBase;
|
||||
pageSize = SST_OS_GetPageSize();
|
||||
|
||||
/* Check if address is aligned to page boundary */
|
||||
if(addr & (pageSize-1))
|
||||
return -1;
|
||||
|
||||
/* Microsoft doesn't believe in bitfields. This switch brought to you by a poor design decision */
|
||||
switch(protectFlags)
|
||||
{
|
||||
/* r/o */
|
||||
case SST_PROTECT_READ: newFlags = PAGE_READONLY; break;
|
||||
|
||||
/* r/w, w/o */
|
||||
case SST_PROTECT_READ | SST_PROTECT_WRITE:
|
||||
case SST_PROTECT_WRITE: newFlags = PAGE_READWRITE; break; /* Win32 doesn't have w/o */
|
||||
|
||||
/* x/o */
|
||||
case SST_PROTECT_EXEC: newFlags = PAGE_EXECUTE; break;
|
||||
|
||||
/* w/x */
|
||||
case SST_PROTECT_WRITE | SST_PROTECT_EXEC: newFlags = PAGE_EXECUTE_READWRITE; break;
|
||||
|
||||
/* r/x */
|
||||
case SST_PROTECT_READ | SST_PROTECT_EXEC: newFlags = PAGE_EXECUTE_READ; break;
|
||||
|
||||
/* r/w/x */
|
||||
case SST_PROTECT_READ | SST_PROTECT_WRITE | SST_PROTECT_EXEC: newFlags = PAGE_EXECUTE_READWRITE; break;
|
||||
}
|
||||
|
||||
if(VirtualProtectEx(GetCurrentProcess(), (void*)addr, roundToPage(pageSize, nrBytes), newFlags, NULL) != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
60
libsst-os/SST_Time_MacOSX.c
Normal file
60
libsst-os/SST_Time_MacOSX.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
SST_Time_MacOSX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 5/30/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os timing functions for MacOSX systems
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Time.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static mach_timebase_info_data_t info;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int __libsst_init_time()
|
||||
{
|
||||
return (mach_timebase_info(&info) == KERN_SUCCESS);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static uint64_t absToNsec(uint64_t abstime)
|
||||
{
|
||||
return abstime * info.numer / info.denom;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMicroTime()
|
||||
{
|
||||
return absToNsec(mach_absolute_time()) / 1000;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_OS_GetMilliTime()
|
||||
{
|
||||
return absToNsec(mach_absolute_time()) / 1000000;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
double SST_OS_GetFloatingTime()
|
||||
{
|
||||
return absToNsec(mach_absolute_time()) / 1000000000.0;
|
||||
}
|
||||
85
libsst-os/SST_Time_POSIX.c
Normal file
85
libsst-os/SST_Time_POSIX.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
SST_Time_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 5/29/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os timing functions for POSIX systems
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Sadly, MacOS X does not implement clock_gettime(), so it has its own file
|
||||
*/
|
||||
|
||||
#include <SST/SST_Time.h>
|
||||
#include <time.h>
|
||||
|
||||
struct timespec freq;
|
||||
|
||||
static clockid_t timeSource =
|
||||
#if defined(CLOCK_MONOTONIC_RAW) /* Linux >= 2.6.28 */
|
||||
CLOCK_MONOTONIC_RAW;
|
||||
#else
|
||||
CLOCK_MONOTONIC;
|
||||
#endif
|
||||
|
||||
int __libsst_init_time()
|
||||
{
|
||||
struct timespec v;
|
||||
int clkOk = (clock_gettime(timeSource, &v) > 0);
|
||||
|
||||
if(!clkOk)
|
||||
{
|
||||
#if defined(CLOCK_MONOTONIC_RAW)
|
||||
timeSource = CLOCK_MONOTONIC;
|
||||
clkOk = (clock_gettime(timeSource, &v) > 0);
|
||||
if(!clkOk)
|
||||
#else
|
||||
timeSource = CLOCK_REALTIME;
|
||||
#endif
|
||||
|
||||
|
||||
if(clock_gettime(timeSource, &v) < 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetMicroTime()
|
||||
{
|
||||
struct timespec v;
|
||||
|
||||
clock_gettime(timeSource, &v);
|
||||
|
||||
return (uint64_t)((v.tv_sec * 1000000) + (v.tv_nsec / 1000));
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetMilliTime() /* Not be confused with Miller Time (TM) :D */
|
||||
{
|
||||
struct timespec v;
|
||||
|
||||
clock_gettime(timeSource, &v);
|
||||
|
||||
return (uint64_t)((v.tv_sec * 1000) + (v.tv_nsec / 1000000));
|
||||
}
|
||||
|
||||
double SST_OS_GetFloatingTime()
|
||||
{
|
||||
struct timespec v;
|
||||
|
||||
clock_gettime(timeSource, &v);
|
||||
|
||||
return (double)v.tv_sec + (v.tv_nsec / 1000000000.0);
|
||||
}
|
||||
|
||||
|
||||
80
libsst-os/SST_Time_Win32.c
Normal file
80
libsst-os/SST_Time_Win32.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
SST_Time_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 5/29/2013
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os timing functions for Win32
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Time.h>
|
||||
#include <windows.h>
|
||||
|
||||
static LARGE_INTEGER freq; /* Frequency, as 64-bit integer */
|
||||
static double dfreq; /* Frequency, as a double value */
|
||||
|
||||
/*
|
||||
Quick note about frequencies:
|
||||
|
||||
x86 PCs typically have various sources of timers, but these 3 are the most common:
|
||||
* RDTSC -- x86 instruction to read a cycle counter, varies per CPU but can be in the low GHz range.
|
||||
* ACPI -- Advanced Configuration and Power Interface timer, about 3.57 MHz (so, about 280 nanosecond accuracy)
|
||||
* i8254 -- Intel chip on keyboard, about 1.193 MHz (so, about 838 nanosecond accuracy)
|
||||
*/
|
||||
|
||||
int __libsst_init_time()
|
||||
{
|
||||
BOOL ok = QueryPerformanceFrequency(&freq);
|
||||
if(ok)
|
||||
dfreq = (double)freq.QuadPart;
|
||||
|
||||
return (int)ok;
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetRawTime()
|
||||
{
|
||||
LARGE_INTEGER v;
|
||||
QueryPerformanceCounter(&v);
|
||||
|
||||
return (uint64_t)v.QuadPart;
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetRawFrequency()
|
||||
{
|
||||
return (uint64_t)freq.QuadPart;
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetMicroTime()
|
||||
{
|
||||
LARGE_INTEGER v;
|
||||
QueryPerformanceCounter(&v);
|
||||
|
||||
return (uint64_t)((v.QuadPart * 1000LL * 1000LL) / freq.QuadPart);
|
||||
}
|
||||
|
||||
uint64_t SST_OS_GetMilliTime() /* Not be confused with Miller Time (TM) :D */
|
||||
{
|
||||
LARGE_INTEGER v;
|
||||
QueryPerformanceCounter(&v);
|
||||
|
||||
return (uint64_t)((v.QuadPart * 1000LL) / freq.QuadPart);
|
||||
}
|
||||
|
||||
double SST_OS_GetFloatingTime()
|
||||
{
|
||||
LARGE_INTEGER v;
|
||||
QueryPerformanceCounter(&v);
|
||||
|
||||
return (double)v.QuadPart / dfreq;
|
||||
|
||||
}
|
||||
152
libsst-os/SST_User_POSIX.c
Normal file
152
libsst-os/SST_User_POSIX.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
SST_User_POSIX.c
|
||||
Author: Patrick Baggett <ptb1@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os user account information functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
|
||||
int __libsst_init_user() { return 1; }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetUserName(char* usernameReturn, int bufferSize)
|
||||
{
|
||||
uid_t euid;
|
||||
struct passwd pwd;
|
||||
struct passwd* ptrpwd = NULL;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
/* Here we using the POSIX '95 extension for reentrant functions */
|
||||
euid = geteuid();
|
||||
if(getpwuid_r(euid, &pwd, buf, sizeof(buf), &ptrpwd) != 0)
|
||||
return -1;
|
||||
|
||||
/* getpwuid_r() will return 0 to indicate success, but it does not indicate that a matching
|
||||
record was found, just that the arguments weren't incorrect. Check if *ptrpwd is still NULL,
|
||||
which means the record wasn't found. */
|
||||
if(ptrpwd == NULL)
|
||||
return 0;
|
||||
|
||||
len = (int)strlen(pwd.pw_name);
|
||||
|
||||
/* Is the user just querying the length? */
|
||||
if(usernameReturn == NULL)
|
||||
return len;
|
||||
|
||||
|
||||
/* Expected case: (more than) enough space -> just do strcpy() */
|
||||
if(bufferSize >= len+1)
|
||||
{
|
||||
strcpy(usernameReturn, pwd.pw_name);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Exceptional case: less than enough space. Copy 'bufferSize'-1 characters, then add NULL terminator. */
|
||||
memcpy(usernameReturn, pwd.pw_name, bufferSize-1);
|
||||
usernameReturn[bufferSize-1] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetUserRealName(char* realnameReturn, int bufferSize)
|
||||
{
|
||||
uid_t euid;
|
||||
struct passwd pwd;
|
||||
struct passwd* ptrpwd = NULL;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
/* Here we using the POSIX '95 extension for reentrant functions */
|
||||
euid = geteuid();
|
||||
if(getpwuid_r(euid, &pwd, buf, sizeof(buf), &ptrpwd) != 0)
|
||||
return -1;
|
||||
|
||||
/* getpwuid_r() will return 0 to indicate success, but it does not indicate that a matching
|
||||
record was found, just that the arguments weren't incorrect. Check if *ptrpwd is still NULL,
|
||||
which means the record wasn't found. */
|
||||
if(ptrpwd == NULL)
|
||||
return 0;
|
||||
|
||||
len = (int)strlen(pwd.pw_gecos);
|
||||
|
||||
/* Is the user just querying the length? */
|
||||
if(realnameReturn == NULL)
|
||||
return len;
|
||||
|
||||
|
||||
/* Expected case: (more than) enough space -> just do strcpy() */
|
||||
if(bufferSize >= len+1)
|
||||
{
|
||||
strcpy(realnameReturn, pwd.pw_gecos);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Exceptional case: less than enough space. Copy 'bufferSize'-1 characters, then add NULL terminator. */
|
||||
memcpy(realnameReturn, pwd.pw_gecos, bufferSize-1);
|
||||
realnameReturn[bufferSize-1] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_OS_GetUserHomeDirectory(char* homedirReturn, int bufferSize)
|
||||
{
|
||||
uid_t euid;
|
||||
struct passwd pwd;
|
||||
struct passwd* ptrpwd = NULL;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
/* Here we using the POSIX '95 extension for reentrant functions */
|
||||
euid = geteuid();
|
||||
if(getpwuid_r(euid, &pwd, buf, sizeof(buf), &ptrpwd) != 0)
|
||||
return -1;
|
||||
|
||||
/* getpwuid_r() will return 0 to indicate success, but it does not indicate that a matching
|
||||
record was found, just that the arguments weren't incorrect. Check if *ptrpwd is still NULL,
|
||||
which means the record wasn't found. */
|
||||
if(ptrpwd == NULL)
|
||||
return 0;
|
||||
|
||||
len = (int)strlen(pwd.pw_dir);
|
||||
|
||||
/* Is the user just querying the length? */
|
||||
if(homedirReturn == NULL)
|
||||
return len;
|
||||
|
||||
|
||||
/* Expected case: (more than) enough space -> just do strcpy() */
|
||||
if(bufferSize >= len+1)
|
||||
{
|
||||
strcpy(homedirReturn, pwd.pw_dir);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Exceptional case: less than enough space. Copy 'bufferSize'-1 characters, then add NULL terminator. */
|
||||
memcpy(homedirReturn, pwd.pw_dir, bufferSize-1);
|
||||
homedirReturn[bufferSize-1] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
197
libsst-os/SST_User_Win32.c
Normal file
197
libsst-os/SST_User_Win32.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
SST_User_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-os user information functions for Win32 systems (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS /* strncpy() isn't deprecated, stupid programming is */
|
||||
|
||||
#include "Win32Private.h"
|
||||
#include <userenv.h>
|
||||
#include <SST/SST_User.h>
|
||||
#include <malloc.h> //_alloca() on Win32
|
||||
|
||||
static HMODULE advapi32_dll = NULL;
|
||||
static BOOL (WINAPI * pfOpenProcessToken)(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Out_ PHANDLE TokenHandle) = NULL;
|
||||
static BOOL (WINAPI * pfGetUserNameA)(_Out_ LPSTR lpBuffer, _Inout_ LPDWORD lpnSize) = NULL;
|
||||
|
||||
static HMODULE userenv_dll = NULL;
|
||||
static BOOL (WINAPI * pfGetUserProfileDirectoryA)(_In_ HANDLE hToken,_Out_opt_ LPSTR lpProfileDir, _Inout_ LPDWORD lpcchSize) = NULL;
|
||||
|
||||
void libsst_free_user()
|
||||
{
|
||||
pfOpenProcessToken = NULL;
|
||||
pfGetUserNameA = NULL;
|
||||
pfGetUserProfileDirectoryA = NULL;
|
||||
|
||||
if(advapi32_dll)
|
||||
{
|
||||
FreeLibrary(advapi32_dll);
|
||||
advapi32_dll = NULL;
|
||||
}
|
||||
|
||||
if(userenv_dll)
|
||||
{
|
||||
FreeLibrary(userenv_dll);
|
||||
userenv_dll = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int __libsst_init_user()
|
||||
{
|
||||
advapi32_dll = LoadLibraryA("advapi32.dll");
|
||||
if(advapi32_dll == NULL)
|
||||
return 0;
|
||||
|
||||
userenv_dll = LoadLibraryA("userenv.dll");
|
||||
if(userenv_dll == NULL)
|
||||
{
|
||||
FreeLibrary(advapi32_dll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load all symbols */
|
||||
/* advapi32.dll */
|
||||
pfOpenProcessToken = (BOOL (WINAPI*)(HANDLE,DWORD,PHANDLE))GetProcAddress(advapi32_dll, "OpenProcessToken");
|
||||
pfGetUserNameA = (BOOL (WINAPI*)(LPSTR, LPDWORD))GetProcAddress(advapi32_dll, "GetUserNameA");
|
||||
|
||||
/* userenv.dll */
|
||||
pfGetUserProfileDirectoryA = (BOOL (WINAPI*)(HANDLE, LPSTR,LPDWORD))GetProcAddress(userenv_dll, "GetUserProfileDirectoryA");
|
||||
|
||||
/* Verify all loaded */
|
||||
if(pfOpenProcessToken == NULL || pfGetUserNameA == NULL || pfGetUserProfileDirectoryA == NULL)
|
||||
{
|
||||
libsst_free_user();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SST_OS_GetUserName(char* usernameReturn, int bufferSize)
|
||||
{
|
||||
DWORD size;
|
||||
|
||||
/* User is querying the username size */
|
||||
if(usernameReturn == NULL)
|
||||
{
|
||||
char dummy[1];
|
||||
|
||||
/* This *should* generate the insufficient buffer error. When it does, it returns
|
||||
the correct size in 'size'. */
|
||||
size = sizeof(dummy);
|
||||
pfGetUserNameA(dummy, &size);
|
||||
|
||||
/* Make sure it really did. */
|
||||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
return (int)size-1;
|
||||
|
||||
/* Some other error :( */
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = (DWORD)bufferSize;
|
||||
if(pfGetUserNameA(usernameReturn, &size) == FALSE)
|
||||
{
|
||||
/* GetUserName() returns false on insufficient space, but that is OK.
|
||||
However, errors for any other reason isn't OK, so catch them here. */
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return -2;
|
||||
}
|
||||
|
||||
return (int)(size-1);
|
||||
}
|
||||
|
||||
int SST_OS_GetUserRealName(char* realnameReturn, int bufferSize)
|
||||
{
|
||||
/* TODO: better implementation here plz */
|
||||
return SST_OS_GetUserName(realnameReturn, bufferSize);
|
||||
}
|
||||
|
||||
int SST_OS_GetUserHomeDirectory(char* homedirReturn, int bufferSize)
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
DWORD size;
|
||||
int retcode;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(homedirReturn && bufferSize < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if(pfOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == FALSE)
|
||||
return -2;
|
||||
|
||||
/* User is querying the username size */
|
||||
if(homedirReturn == NULL)
|
||||
{
|
||||
char dummy[1]; /* See comment block */
|
||||
size = 0;
|
||||
|
||||
/*
|
||||
Bug in GetUserProfileDirectoryA() impl: NULL for 2nd param should be allowed but isn't.
|
||||
|
||||
MSDN: "If the buffer specified by lpProfileDir is not large enough or lpProfileDir is NULL, the function fails
|
||||
and this parameter receives the necessary buffer size, including the terminating null character."
|
||||
|
||||
However, in practice, when I set the second param to NULL, `size` remains zero.
|
||||
*/
|
||||
|
||||
|
||||
pfGetUserProfileDirectoryA(hToken, dummy, &size);
|
||||
|
||||
if(size == 0)
|
||||
retcode = -3;
|
||||
else
|
||||
retcode = (int)(size-1);
|
||||
}
|
||||
else /* Actually getting the size */
|
||||
{
|
||||
/* Set the size to the user provided size and query*/
|
||||
size = (DWORD)bufferSize;
|
||||
if(pfGetUserProfileDirectoryA(hToken, homedirReturn, &size) == FALSE)
|
||||
{
|
||||
|
||||
/* This gets tricky: the function doesn't write partial paths, so we have to first detect
|
||||
if the error was due to buffer size */
|
||||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
char* tmpbuf = (char*)_alloca(size);
|
||||
|
||||
/* OK, now we've ensured we have a correctly-sized buffer, so call it again. */
|
||||
if(pfGetUserProfileDirectoryA(hToken, tmpbuf, &size) == FALSE)
|
||||
{
|
||||
/* Failed second time around, doh -- give up */
|
||||
retcode = -4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Success -- copy n-1 characters, then null terminate */
|
||||
strncpy(homedirReturn, tmpbuf, bufferSize-1);
|
||||
homedirReturn[bufferSize-1] = 0;
|
||||
retcode = (int)size-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Success */
|
||||
retcode = (int)(size-1);
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
return retcode;
|
||||
}
|
||||
168
libsst-os/Win32Private.h
Normal file
168
libsst-os/Win32Private.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Win32Private.h
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/23/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Private data structures for Win32 implementation of libsst-os. Not to be distributed
|
||||
as part of public SDK headers.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32PRIVATE_H
|
||||
#define _WIN32PRIVATE_H
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
#include <pstdint.h>
|
||||
|
||||
#if defined(__GNUC__) /* Missing Windows 7 API on various GCC targets, remove when is fixed. */
|
||||
typedef ULONG_PTR KAFFINITY;
|
||||
|
||||
typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
|
||||
RelationProcessorCore,
|
||||
RelationNumaNode,
|
||||
RelationCache,
|
||||
RelationProcessorPackage,
|
||||
RelationGroup,
|
||||
RelationAll = 0xffff
|
||||
} LOGICAL_PROCESSOR_RELATIONSHIP;
|
||||
|
||||
typedef enum _PROCESSOR_CACHE_TYPE {
|
||||
CacheUnified,
|
||||
CacheInstruction,
|
||||
CacheData,
|
||||
CacheTrace
|
||||
} PROCESSOR_CACHE_TYPE;
|
||||
|
||||
typedef struct _CACHE_DESCRIPTOR {
|
||||
BYTE Level;
|
||||
BYTE Associativity;
|
||||
WORD LineSize;
|
||||
DWORD Size;
|
||||
PROCESSOR_CACHE_TYPE Type;
|
||||
} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR;
|
||||
|
||||
typedef struct _GROUP_AFFINITY {
|
||||
KAFFINITY Mask;
|
||||
WORD Group;
|
||||
WORD Reserved[3];
|
||||
} GROUP_AFFINITY, *PGROUP_AFFINITY;
|
||||
|
||||
typedef struct _PROCESSOR_NUMBER {
|
||||
WORD Group;
|
||||
BYTE Number;
|
||||
BYTE Reserved;
|
||||
} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
|
||||
|
||||
typedef struct _PROCESSOR_GROUP_INFO {
|
||||
BYTE MaximumProcessorCount;
|
||||
BYTE ActiveProcessorCount;
|
||||
BYTE Reserved[38];
|
||||
KAFFINITY ActiveProcessorMask;
|
||||
} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO;
|
||||
|
||||
typedef struct _PROCESSOR_RELATIONSHIP {
|
||||
BYTE Flags;
|
||||
BYTE Reserved[21];
|
||||
WORD GroupCount;
|
||||
GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
|
||||
} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP;
|
||||
|
||||
typedef struct _NUMA_NODE_RELATIONSHIP {
|
||||
DWORD NodeNumber;
|
||||
BYTE Reserved[20];
|
||||
GROUP_AFFINITY GroupMask;
|
||||
} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP;
|
||||
|
||||
typedef struct _CACHE_RELATIONSHIP {
|
||||
BYTE Level;
|
||||
BYTE Associativity;
|
||||
WORD LineSize;
|
||||
DWORD CacheSize;
|
||||
PROCESSOR_CACHE_TYPE Type;
|
||||
BYTE Reserved[20];
|
||||
GROUP_AFFINITY GroupMask;
|
||||
} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP;
|
||||
|
||||
typedef struct _GROUP_RELATIONSHIP {
|
||||
WORD MaximumGroupCount;
|
||||
WORD ActiveGroupCount;
|
||||
BYTE Reserved[20];
|
||||
PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY];
|
||||
} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
|
||||
|
||||
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
|
||||
ULONG_PTR ProcessorMask;
|
||||
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
|
||||
union {
|
||||
struct {
|
||||
BYTE Flags;
|
||||
} ProcessorCore;
|
||||
struct {
|
||||
DWORD NodeNumber;
|
||||
} NumaNode;
|
||||
CACHE_DESCRIPTOR Cache;
|
||||
ULONGLONG Reserved[2];
|
||||
};
|
||||
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
|
||||
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
|
||||
DWORD Size;
|
||||
union {
|
||||
PROCESSOR_RELATIONSHIP Processor;
|
||||
NUMA_NODE_RELATIONSHIP NumaNode;
|
||||
CACHE_RELATIONSHIP Cache;
|
||||
GROUP_RELATIONSHIP Group;
|
||||
};
|
||||
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
|
||||
|
||||
BOOL WINAPI GetLogicalProcessorInformationEx(
|
||||
LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType,
|
||||
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
|
||||
PDWORD ReturnedLength);
|
||||
|
||||
BOOL WINAPI GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength);
|
||||
|
||||
|
||||
BOOL WINAPI SetThreadIdealProcessorEx(HANDLE hThread, PPROCESSOR_NUMBER lpIdealProcessor, PPROCESSOR_NUMBER lpPreviousIdealProcessor);
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
typedef struct SST_File_Win32
|
||||
{
|
||||
HANDLE hFile; /* Handle from CreateFile() */
|
||||
HANDLE hMap; /* Handle from CreateFileMapping() */
|
||||
int isAsync; /* Is this file in async mode */
|
||||
DWORD accessFlags; /* Flags for access used in CreateFileA() */
|
||||
|
||||
#ifdef _DEBUG
|
||||
int nrMmaps; /* Number of outstanding memory maps */
|
||||
#endif
|
||||
} SST_File_Win32;
|
||||
|
||||
typedef struct SST_MemoryMap_Win32
|
||||
{
|
||||
uint64_t offset; /* Offset parameter as given to SST_OS_MmapCreate() */
|
||||
size_t len; /* Length parameter as given to SST_OS_MmapCreate() */
|
||||
void* base; /* Returned base address from SST_OS_MmapCreate() */
|
||||
|
||||
#ifdef _DEBUG
|
||||
SST_File_Win32* owner; /* File that created this memory map */
|
||||
#endif
|
||||
} SST_MemoryMap_Win32;
|
||||
|
||||
#endif
|
||||
200
libsst-os/libsst-os.vcxproj
Normal file
200
libsst-os/libsst-os.vcxproj
Normal file
@@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4BAC6D63-C2E8-43F7-87EA-EF953CBFDDD3}</ProjectGuid>
|
||||
<RootNamespace>libsstos</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\vsyasm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\Lib\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\Lib\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\Lib\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\Lib\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>SST_ASSERT_NODEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>SST_ASSERT_NODEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SST_Alloc.c" />
|
||||
<ClCompile Include="SST_Assert.c" />
|
||||
<ClCompile Include="SST_Assert_Win32.c" />
|
||||
<ClCompile Include="SST_CPU_Win32.c" />
|
||||
<ClCompile Include="SST_DynLib_Win32.c" />
|
||||
<ClCompile Include="SST_Endian.c" />
|
||||
<ClCompile Include="SST_File_Win32.c" />
|
||||
<ClCompile Include="SST_FileSys_Win32.c" />
|
||||
<ClCompile Include="SST_Mmap_Win32.c" />
|
||||
<ClCompile Include="SST_OSInit.c" />
|
||||
<ClCompile Include="SST_SafeArithmetic.c" />
|
||||
<ClCompile Include="SST_SysMem_Win32.c" />
|
||||
<ClCompile Include="SST_Time_Win32.c" />
|
||||
<ClCompile Include="SST_User_Win32.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<YASM Include="SST_CPUCache_x86-64-win64.asm">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</YASM>
|
||||
<YASM Include="SST_CPUCache_x86.asm">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</YASM>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Time.h" />
|
||||
<ClInclude Include="Win32Private.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Alloc.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Assert.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Build.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_CPU.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_CPUCache.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_DynLib.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Endian.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_File.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_FileSys.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Mmap.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_OS.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_SafeArithmetic.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_SysMem.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_User.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\libsst-atomic\libsst-atomic.vcxproj">
|
||||
<Project>{43ed481f-c4a3-40ed-81a3-46c43dc4eb1e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\vsyasm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
115
libsst-os/libsst-os.vcxproj.filters
Normal file
115
libsst-os/libsst-os.vcxproj.filters
Normal file
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SST_Alloc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Assert.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Assert_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_CPU_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_DynLib_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Endian.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_File_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_FileSys_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Mmap_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_SafeArithmetic.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_SysMem_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_User_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Time_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_OSInit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<YASM Include="SST_CPUCache_x86-64-win64.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</YASM>
|
||||
<YASM Include="SST_CPUCache_x86.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</YASM>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Win32Private.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Alloc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Assert.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Build.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_CPU.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_CPUCache.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_DynLib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Endian.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_File.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_FileSys.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Mmap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_OS.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_SafeArithmetic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_SysMem.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_User.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Time.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
BIN
libsst-os/obj/x86-64/release/SST_Alloc.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Alloc.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_Assert.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Assert.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_Assert_Generic.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Assert_Generic.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_CPUCache_x86-64.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_CPUCache_x86-64.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_CPU_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_CPU_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_DynLib_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_DynLib_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_Endian.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Endian.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_FileSys_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_FileSys_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_File_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_File_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_Mmap_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Mmap_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_OSInit.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_OSInit.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_SafeArithmetic.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_SafeArithmetic.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_SysMem_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_SysMem_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_Time_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_Time_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-os/obj/x86-64/release/SST_User_POSIX.o
Normal file
BIN
libsst-os/obj/x86-64/release/SST_User_POSIX.o
Normal file
Binary file not shown.
38
libsst-os/sources-POSIX.mk
Normal file
38
libsst-os/sources-POSIX.mk
Normal file
@@ -0,0 +1,38 @@
|
||||
# libsst-os/Source/sources-POSIX.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 12/23/2011
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for POSIX-compliant systems. This reduces the amount
|
||||
# of copy/pasting for different UNIX configurations.
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC := \
|
||||
SST_DynLib_POSIX.c \
|
||||
SST_FileSys_POSIX.c \
|
||||
SST_File_POSIX.c \
|
||||
SST_SysMem_POSIX.c \
|
||||
SST_CPU_POSIX.c \
|
||||
SST_Mmap_POSIX.c \
|
||||
SST_User_POSIX.c \
|
||||
SST_Alloc.c \
|
||||
SST_Assert.c \
|
||||
SST_Assert_Generic.c \
|
||||
SST_Endian.c \
|
||||
SST_SafeArithmetic.c \
|
||||
SST_OSInit.c \
|
||||
|
||||
# MacOS X doesn't have POSIX realtime extension, so it needs a different implementation. Le sigh.
|
||||
ifeq ($(OS),Darwin)
|
||||
SRC += SST_Time_MacOSX.c
|
||||
else
|
||||
SRC += SST_Time_POSIX.c
|
||||
endif
|
||||
18
libsst-os/sources-Solaris.mk
Normal file
18
libsst-os/sources-Solaris.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
# libsst-os/sources-Solaris.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 6/21/2012
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for Solaris
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
include sources-POSIX.mk
|
||||
|
||||
28
libsst-os/sources-Win32.mk
Normal file
28
libsst-os/sources-Win32.mk
Normal file
@@ -0,0 +1,28 @@
|
||||
# libsst-os/sources-Win32.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 11/09/2012
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for Win32 systems.
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC := \
|
||||
SST_DynLib_Win32.c \
|
||||
SST_FileSys_Win32.c \
|
||||
SST_File_Win32.c \
|
||||
SST_SysMem_Win32.c \
|
||||
SST_CPU_Win32.c \
|
||||
SST_Mmap_Win32.c \
|
||||
SST_Assert_Win32.c \
|
||||
SST_Alloc.c \
|
||||
SST_Assert.c \
|
||||
SST_Endian.c \
|
||||
SST_SafeArithmetic.c
|
||||
Reference in New Issue
Block a user