Changeset View
Standalone View
sys/sys/smp.h
Show First 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | |||||||||||||||||||||||
void smp_rendezvous_action(void); | void smp_rendezvous_action(void); | ||||||||||||||||||||||
extern struct mtx smp_ipi_mtx; | extern struct mtx smp_ipi_mtx; | ||||||||||||||||||||||
#endif /* SMP */ | #endif /* SMP */ | ||||||||||||||||||||||
int quiesce_all_cpus(const char *, int); | int quiesce_all_cpus(const char *, int); | ||||||||||||||||||||||
int quiesce_cpus(cpuset_t, const char *, int); | int quiesce_cpus(cpuset_t, const char *, int); | ||||||||||||||||||||||
void cpus_fence_seq_cst(void); | |||||||||||||||||||||||
jeff: I don't really understand what the abbreviations are. I understand the code. Can you document… | |||||||||||||||||||||||
mjgAuthorUnsubmitted Done Inline Actionsthey come from c11 and are already used elsewhere in the tree. there are no strict requirements for any of the consumers, apart from replacing whatever fence they had with a compiler barrier. i can add a comment above the func itself. In fact I have plans for a consumer which most definitely does not use critical_enter/exit. mjg: they come from c11 and are already used elsewhere in the tree.
there are no strict… | |||||||||||||||||||||||
kibUnsubmitted Not Done Inline Actionsseq_cst means sequentially consistent, it is common abbreviation, indeed seemingly started from the C++/java memory model working group. I have some doubts that this form of the strongest possible fence semantic is really needed there (and mjg does not provide any reasoning, as usual). But even if any weaker form would suffice, sequentially consistent fence is also correct. In fact, the recommendations are to use seq_cst by default and only weaken it when there are performance implications. kib: seq_cst means sequentially consistent, it is common abbreviation, indeed seemingly started from… | |||||||||||||||||||||||
mjgAuthorUnsubmitted Done Inline ActionsIt's the same scheme as used for vfs_op_* and has roughly the same amount of explanation, so did not see the need to elaborate. So how about this: It allows you to convert the following: foo = 1; into this: foo = 1; mjg: It's the same scheme as used for vfs_op_* and has roughly the same amount of explanation, so… | |||||||||||||||||||||||
mjgAuthorUnsubmitted Done Inline Actions
Both _rel and _acq expand to compiler barriers on amd64 which still allows the following to be reordered so that baz is loaded first: foo = 1; So in this particular case, assuming lock_prof_enable == 1: td->td_critnest++; can turn into:
This can also fail the other way where we read td_critnest first prior to setting lock_prof_enable to 0. mjg: > I have some doubts that this form of the strongest possible fence semantic is really needed… | |||||||||||||||||||||||
kibUnsubmitted Not Done Inline ActionsNo, x86 do not reorder loads. Also, IRETQ is serializing, so if you handle the interrupt, you are guaranteed that seq_cst fence was injected. kib: No, x86 do not reorder loads.
Also, IRETQ is serializing, so if you handle the interrupt, you… | |||||||||||||||||||||||
mjgAuthorUnsubmitted Done Inline Actionsamd64 can reorder a load with a store to a different location, this is precisely what I'm preventing with the fence. The current code already happens to have several barriers stemming from handling of IPIs, I inject this for everyone since it's simple and does not require any hackery. mjg: amd64 can reorder a load with a store to a different location, this is precisely what I'm… | |||||||||||||||||||||||
void smp_no_rendezvous_barrier(void *); | void smp_no_rendezvous_barrier(void *); | ||||||||||||||||||||||
void smp_rendezvous(void (*)(void *), | void smp_rendezvous(void (*)(void *), | ||||||||||||||||||||||
void (*)(void *), | void (*)(void *), | ||||||||||||||||||||||
void (*)(void *), | void (*)(void *), | ||||||||||||||||||||||
void *arg); | void *arg); | ||||||||||||||||||||||
void smp_rendezvous_cpus(cpuset_t, | void smp_rendezvous_cpus(cpuset_t, | ||||||||||||||||||||||
void (*)(void *), | void (*)(void *), | ||||||||||||||||||||||
void (*)(void *), | void (*)(void *), | ||||||||||||||||||||||
void (*)(void *), | void (*)(void *), | ||||||||||||||||||||||
void *arg); | void *arg); | ||||||||||||||||||||||
#endif /* !LOCORE */ | #endif /* !LOCORE */ | ||||||||||||||||||||||
#endif /* _KERNEL */ | #endif /* _KERNEL */ | ||||||||||||||||||||||
#endif /* _SYS_SMP_H_ */ | #endif /* _SYS_SMP_H_ */ |
I don't really understand what the abbreviations are. I understand the code. Can you document the functions with a one-liner? You should also detail the requirements for consumers. Like requiring critical_enter() etc.