seL4/src/util.c
Adrian Danis 5552c6c6d9 mark memset and memcpy as VISIBLE
When compiling the kernel as a whole program it is possible that these functions may
be inlined and not emitted in the resulting binary. However at the same time the
compiler may itself emit calls to these functions. Marking these functions as
externally visible tells the compiler that there may be more usages of them than
it sees immediately in the source code, in this cases usages that the compiler
itself is going to generate
2017-06-16 14:25:50 +10:00

143 lines
3 KiB
C

/*
* Copyright 2014, General Dynamics C4 Systems
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <assert.h>
#include <stdint.h>
#include <util.h>
/*
* memzero needs a custom type that allows us to use a word
* that has the aliasing properties of a char.
*/
typedef unsigned long __attribute__((__may_alias__)) ulong_alias;
/*
* Zero 'n' bytes of memory starting from 's'.
*
* 'n' and 's' must be word aligned.
*/
void
memzero(void *s, unsigned long n)
{
uint8_t *p = s;
/* Ensure alignment constraints are met. */
assert((unsigned long)s % sizeof(unsigned long) == 0);
assert(n % sizeof(unsigned long) == 0);
/* We will never memzero an area larger than the largest current
live object */
/** GHOSTUPD: "(gs_get_assn cap_get_capSizeBits_'proc \<acute>ghost'state = 0
\<or> \<acute>n <= gs_get_assn cap_get_capSizeBits_'proc \<acute>ghost'state, id)" */
/* Write out words. */
while (n != 0) {
*(ulong_alias *)p = 0;
p += sizeof(ulong_alias);
n -= sizeof(ulong_alias);
}
}
void* VISIBLE
memset(void *s, unsigned long c, unsigned long n)
{
uint8_t *p;
/*
* If we are only writing zeros and we are word aligned, we can
* use the optimized 'memzero' function.
*/
if (likely(c == 0 && ((unsigned long)s % sizeof(unsigned long)) == 0 && (n % sizeof(unsigned long)) == 0)) {
memzero(s, n);
} else {
/* Otherwise, we use a slower, simple memset. */
for (p = (uint8_t *)s; n > 0; n--, p++) {
*p = (uint8_t)c;
}
}
return s;
}
void* VISIBLE
memcpy(void* ptr_dst, const void* ptr_src, unsigned long n)
{
uint8_t *p;
const uint8_t *q;
for (p = (uint8_t *)ptr_dst, q = (const uint8_t *)ptr_src; n; n--, p++, q++) {
*p = *q;
}
return ptr_dst;
}
int PURE
strncmp(const char* s1, const char* s2, int n)
{
word_t i;
int diff;
for (i = 0; i < n; i++) {
diff = ((unsigned char*)s1)[i] - ((unsigned char*)s2)[i];
if (diff != 0 || s1[i] == '\0') {
return diff;
}
}
return 0;
}
long CONST
char_to_long(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
}
return -1;
}
long PURE
str_to_long(const char* str)
{
unsigned int base;
long res;
long val = 0;
char c;
/*check for "0x" */
if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
base = 16;
str += 2;
} else {
base = 10;
}
if (!*str) {
return -1;
}
c = *str;
while (c != '\0') {
res = char_to_long(c);
if (res == -1 || res >= base) {
return -1;
}
val = val * base + res;
str++;
c = *str;
}
return val;
}