OSDev.org

The Place to Start for Operating System Developers
It is currently Mon May 20, 2019 11:06 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: memset() trouble
PostPosted: Sat Mar 16, 2019 4:30 pm 
Offline

Joined: Wed Feb 13, 2019 3:07 pm
Posts: 20
I have the function:
Code:
ordered_array_t place_ordered_array(void *addr, u32int max_size, lessthan_predicate_t less_than)
{
    ordered_array_t to_ret;
    to_ret.array = (type_t*)addr;
    memset(to_ret.array, 0, max_size*sizeof(type_t));
    to_ret.size = 0;
    to_ret.max_size = max_size;
    to_ret.less_than = less_than;
    return to_ret;
}


The code doesn't execute after memset().
addr = 0xc000,
max_size*sizeof(type_t) is around 500 000.

The function is called by this, that is called by this, that is called in the kernel.

memset() source.

How to fix if?


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Sat Mar 16, 2019 11:50 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 186
Well, what does happen? Have you asked a debugger? Is it possible the memset just takes a while?

The code looks reasonable enough, except of course for the fact that you don't have the four mem* functions GCC requires even in freestanding mode. You must have an implementation of memset(), memcpy(), memcmp(), and memmove(). You only have memory_set(), which isn't the same.

Here is my compiler support library. In case it actually is creative enough to even get a copyright, it is hereby released into the public domain. Optimization is left as an excercise to the reader, if need be. Oh yeah, and it is C, at least C99, and won't work as C++.

Code:
#include <stddef.h>

void *memcpy(void* restrict a, const void *restrict b, size_t len) {
    unsigned char *d = a;
    const unsigned char *s = b;

    if (d != s) {
        while (len--)
            *d++ = *s++;
    }
    return a;
}

void *memmove(void* a, const void* b, size_t len) {
    unsigned char *d = a;
    const unsigned char *s = b;
    if (d <= s || d >= s + len)
        return memcpy(d, s, len);
    d += len;
    s += len;
    while (len--)
        *--d = *--s;
    return a;
}

void *memset(void *a, int v, size_t len) {
    unsigned char *d = a;
    while (len--)
        *d++ = v;
    return a;
}

int memcmp(const void * restrict a, const void * restrict b, size_t len) {
    int r = 0;
    const unsigned char *x = a;
    const unsigned char *y = b;

    while (len--) {
        r = *x - *y;
        if (r)
            return r;
        x++, y++;
    }
    return 0;
}


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Sun Mar 17, 2019 7:22 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 271
nullplan wrote:
Well, what does happen? Have you asked a debugger? Is it possible the memset just takes a while?
Yeah that would be nice to know.

Quote:
The code looks reasonable enough, except of course for the fact that you don't have the four mem* functions GCC requires even in freestanding mode. You must have an implementation of memset(), memcpy(), memcmp(), and memmove(). You only have memory_set(), which isn't the same.
That's not entirely true. First without a memset() implementation the code wouldn't compile and link in the first place. Second, gcc has a dirty, totally libgcc independent hack for the mem functions (which works in freestanding mode too), it includes the __builtin_memset() in the final executable if memset() implementation otherwise not found. This is highly non-standard, and for example Clang doesn't do it.
Quote:
The ISO C90 functions abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, exp, fabs, floor, fmod, fprintf, fputs, frexp, fscanf, isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper, labs, ldexp, log10, log, malloc, memchr, memcmp, memcpy, memset, modf, pow, printf, putchar, puts, scanf, sinh, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, tanh, tan, vfprintf, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). All of these functions have corresponding versions prefixed with __builtin_.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Mon Mar 18, 2019 12:51 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1518
bzt wrote:
That's not entirely true. First without a memset() implementation the code wouldn't compile and link in the first place. Second, gcc has a dirty, totally libgcc independent hack for the mem functions (which works in freestanding mode too), it includes the __builtin_memset() in the final executable if memset() implementation otherwise not found. This is highly non-standard, and for example Clang doesn't do it.

I don't see where you're getting that from the documentation. The __builtin_memset() function doesn't exist, it's just an optimizer hint that allows GCC to choose either a memset() function reference or equivalent inline code. It's the same for all of the builtin functions.

The special case for memcpy, memmove, memset and memcmp in freestanding mode is due to GCC's optimizer. If you write code that's equivalent to one of those four functions, GCC will optimize it into the equivalent builtin function, and the builtin function may translate to a function call.


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Tue Mar 19, 2019 10:05 am 
Offline

Joined: Wed Feb 13, 2019 3:07 pm
Posts: 20
nullplan wrote:
Well, what does happen? Have you asked a debugger? Is it possible the memset just takes a while?

The code looks reasonable enough, except of course for the fact that you don't have the four mem* functions GCC requires even in freestanding mode. You must have an implementation of memset(), memcpy(), memcmp(), and memmove(). You only have memory_set(), which isn't the same.

Here is my compiler support library. In case it actually is creative enough to even get a copyright, it is hereby released into the public domain. Optimization is left as an excercise to the reader, if need be. Oh yeah, and it is C, at least C99, and won't work as C++.

Code:
#include <stddef.h>

void *memcpy(void* restrict a, const void *restrict b, size_t len) {
    unsigned char *d = a;
    const unsigned char *s = b;

    if (d != s) {
        while (len--)
            *d++ = *s++;
    }
    return a;
}

void *memmove(void* a, const void* b, size_t len) {
    unsigned char *d = a;
    const unsigned char *s = b;
    if (d <= s || d >= s + len)
        return memcpy(d, s, len);
    d += len;
    s += len;
    while (len--)
        *--d = *--s;
    return a;
}

void *memset(void *a, int v, size_t len) {
    unsigned char *d = a;
    while (len--)
        *d++ = v;
    return a;
}

int memcmp(const void * restrict a, const void * restrict b, size_t len) {
    int r = 0;
    const unsigned char *x = a;
    const unsigned char *y = b;

    while (len--) {
        r = *x - *y;
        if (r)
            return r;
        x++, y++;
    }
    return 0;
}


What information you want to get from debuger?

The code from initialise_pagint()
Code:
// Now, enable paging!
    switch_page_directory(kernel_directory);
    print_s("test");
    // Initialise the kernel heap.
    kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
    print_s("testFInal");
}

"test" is being print, but "testFinal" not.


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Tue Mar 19, 2019 9:20 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 186
Shvets04 wrote:
What information you want to get from debuger?

The code from initialise_pagint()
Code:
// Now, enable paging!
    switch_page_directory(kernel_directory);
    print_s("test");
    // Initialise the kernel heap.
    kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
    print_s("testFInal");
}

"test" is being print, but "testFinal" not.

Again: What does happen? That's the question you should be asking yourself. Run the code and when you think it's hanging, break into the debugger and see where you are, and why you are in an infinite loop.


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Mon Apr 01, 2019 7:28 pm 
Offline

Joined: Sat Dec 29, 2018 3:09 am
Posts: 10
If something is breaking I would look at the size parameter you pass to memset().


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Tue Apr 02, 2019 4:59 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 271
Octocontrabass wrote:
I don't see where you're getting that from the documentation. The __builtin_memset() function doesn't exist
Read the documentation more carefully. I've linked it and also quoted from the doc, but let's quote that part again:
gcc manual wrote:
...memset,...
All of these functions have corresponding versions prefixed with __builtin_.
If you still have doubt, check out the source: https://github.com/gcc-mirror/gcc/blob/master/gcc/builtins.c. There's no point in denying the obvious.

To the OP: we still don't know what happens, and what arguments you pass to memset. We can't help without those. A debugger can tell you the actual parameters used.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: memset() trouble
PostPosted: Tue Apr 02, 2019 11:25 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 570
Everything that nullplan and Octocontrabass said is entirely correct. __builtin_memset() still calls into the memset symbol in many situations, regardless of whether __builtin_memset is used or not. This behavior is consistent with Clang. Indeed, it really works the other way around: When GCC sees a call to memset() (or any of the other builtins) in your code, it internally replaces the call by __builtin_memset() (which is a keyword, not a function!). It then applies optimizations and tries to elide the builtin. If that does not work, it does generate a call to the memset symbol (this is documented on the page that bzt cited: "Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function is emitted."). For example, this can be verified by compiling sin(constant): GCC will just replace the call by its result at compile time.

In the case of the snippet above, this behavior can be avoided with -fno-builtin (which is implied by -ffreestanding), but you cannot rely on this fact for the mem* functions, as documented by the GCC manual: "Most of the compiler support routines used by GCC are present in libgcc, but there are a few exceptions. GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. Finally, if __builtin_trap is used, and the target does not implement the trap pattern, then GCC emits a call to abort." Note that still is still independent on whether you write __builtin_memset() or memset() in your source. All that -fno-builtin does is making the memset not degrade into __builtin_memset automatically. This can be seen from this snippet, which uses __builtin_memset if you drop the -fno-builtin.

Thus, I suspect the OP's issue is the one that nullplan brought up -- you need to have a memset() symbol that does the right thing, otherwise, you're breaking GCC's expectations.

_________________
managarm: A microkernel-based OS that is capable of running a Wayland desktop


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group