New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to get the ID of a std.os.Thread, and to get ID of current thread #1316

Closed
mdsteele opened this Issue Aug 2, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@mdsteele
Contributor

mdsteele commented Aug 2, 2018

Being able to get the current thread ID would be handy for various things. Here are two specific examples that are relevant to the project I'm working on at the moment:

  • When implementing a mutex, you can store the ID of the locking thread to help detect deadlock where the same thread tries to lock it again, or to detect a different thread trying to unlock.
  • When implementing a thread-safe allocator, you can map different threads to different subheaps to help avoid false sharing (note that a thread-local variable is unhelpful here, because a thread may sometimes need to access the subheap of another thread).

Strawman proposal for code in std/os/index.zig:

const ThreadId = usize; // or something else, possibly depending on builtin.os

pub const Thread = struct {
    // ...existing code...

    /// Returns the ID of this thread object.
    pub fn id(self: *const this) ThreadId {
        return if (use_pthreads) {
            self.data.handle
        } else switch (builtin.os) {
            builtin.Os.linux => @bitCast(u32, self.data.pid),
            builtin.Os.windows => @ptrToInt(self.data.handle),
            else => @compileError("Unsupported OS"),
        };
    }

    /// Returns the ID of the calling thread.
    pub fn current() ThreadId {
        return if (use_pthreads) {
            c.pthread_self()
        } else switch (builtin.os) {
            // ...etc... (if I knew how to do this part, I would've just sent a PR)
        };
    }
};
@mdsteele

This comment has been minimized.

Contributor

mdsteele commented Aug 2, 2018

On a second look, I think I can try to put together a PR for this after all. (Also, the code above doesn't compile, so that needs some work...)

@andrewrk andrewrk added this to the 0.4.0 milestone Aug 2, 2018

@andrewrk

This comment has been minimized.

Member

andrewrk commented Aug 2, 2018

I think you can accomplish this in the places you need it (e.g. in your allocator code) with thread local storage (#924) like this:

var next_global_id: usize = 1;
threadlocal var thread_id: usize = 0;

fn getThreadId() usize {
     const id = thread_id;
     if (id != 0) return id;
     const allocated_id = @atomicRmw(usize, &next_global_id, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
     thread_id = allocated_id;
     return allocated_id;
}

Every thread gets assigned a unique id, which you could use in your mutex or allocator use cases to distinguish.

This getThreadId function could be available in the standard library to use. What's nice about this is that:

  • if no one uses it, it doesn't get compiled and the TLS variable is not necessary
  • if many uses of it occur, they share the same implementation.

kristate added a commit to kristate/zig that referenced this issue Aug 4, 2018

mdsteele added a commit to mdsteele/zig that referenced this issue Aug 4, 2018

@andrewrk andrewrk closed this in 86d1cc8 Aug 6, 2018

@andrewrk andrewrk modified the milestones: 0.4.0, 0.3.0 Sep 28, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment