Skip to content
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

global little-locks (change_dir_lock, global_args_lock) are sloppy and wrong #8140

Closed
bblum opened this issue Jul 31, 2013 · 5 comments
Closed
Labels
A-concurrency Area: Concurrency C-cleanup Category: PRs that clean code up or issues documenting cleanup.

Comments

@bblum
Copy link
Contributor

bblum commented Jul 31, 2013

rust_builtin.cpp has some builtins for accessing the "change_dir_lock" and the "global_args_lock". As evidenced by the fact that both of them accidentally use the same lock(!), this approach is prone to error. It would be better if the associated places in rust code could just use unstable::sync::LittleLock directly.

For extra bonus points, we should be able to have unsafe mutable global LittleLocks that are lazily initialized in LittleLock::lock(). This would allow atomically to become totally private to unstable::sync, as #7872 really wants.

(But, I can't figure out what's going on with the use of atomically instead of LittleLock in unstable::dynamic_lib::check_for_errors_in. @sstewartgallus, git blame points to you -- can you shed light on this?)

@bblum
Copy link
Contributor Author

bblum commented Jul 31, 2013

(at least they don't have the error where the lock function takes one of the locks but the unlock drops the other. that would be really embarrassing. (but they could!))

@mstewartgallus
Copy link
Contributor

@bblum Yeah, I'm sorry. I should probable fix that. Here's why I used atomically in the dynamic library support. I believe the error state in Win32, and most (I don't believe it's actually required) POSIX implementations are thread-local to each operating system thread. I didn't know if the error state was also thread-local to each Rust task (Rust tasks are layered on top of OS threads) so I thought that multiple Rust tasks could end up using the same dynamic library error state, and step on each other's toes. That's why I stopped the Rust task from context switching using atomically. I think I may have been mistaken, and confused about thread local storage, and that the use of atomically might not be needed.

@brson
Copy link
Contributor

brson commented Jul 31, 2013

This will require creating platform-specific bindings to mutexes so that we can declare them statically.

@bblum
Copy link
Contributor Author

bblum commented Jul 31, 2013

@brson: My idea for it was something like this, sort of like the trick that #7748 would use.

fn lock(...) {
    if self.l.is_null() { // need barrier here?
        let attempted_thing = rust_create_little_lock();
        compare_and_swap(&mut self.l, attempted_thing, ptr::null()) // which barrier?
    }
    // actual lock routine follows
}

Doesn't need any more platform-specific stuff than the existing rust_create_little_lock builtin. (But I didn't feel up to figuring out the barriers today.) (Actually, I think no barriers are needed; you just need to be careful to read the result of the compare and swap and use that as the new pointer if you lose the race.)

@alexcrichton
Copy link
Member

Closing now that this has been fixed. We now have a lazily initialized static mutex type which serves to be a small short-lived (and properly scoped) lock for sections like this. Right now this does not leverage the atomically function, but this function is going to have to be removed anyway once green scheduling is removed from libstd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-concurrency Area: Concurrency C-cleanup Category: PRs that clean code up or issues documenting cleanup.
Projects
None yet
Development

No branches or pull requests

4 participants