My strategy here is to define _ARM_ARCH_BE8 macro in arm/cdefs.h, if
__ARMEB__ && _ARM_ARCH_6.
Use this macro to determine whether system is compiled for and running on
BE8 mode or not.
Note that, for __ARMEB__, some conditions become compile-time constants
determined by _ARM_ARCH_BE8 macro, e.g., whether BE8 or BE32 are accepted
as a userland binary, or unaligned memory access is possible or not.
- binary compatibility with earmv7{,hf}eb and later, as well as
COMPAT_NETBSD32 on aarch64eb
- unaligned memory access
whereas compatibility with earmv5{,hf}eb and prior is lost.
As we have never released kernel and userland for earmv6{,hf}eb yet,
this does not causes any compatibility problems.
Discussed on port-arm and tech-toolchain.
The special path entry is called .DOTLAST, therefore the local variable
should have the same name.
A variable named 'base' must not point to the slash of a pathname. It
may only point to the character after the slash, everything else is
confusing, even if it's only for a brief moment.
ixgbe_legacy_irq(), too.
> An interrupt might not arrive when a module is inserted. When an link
> status change interrupt occurred and the driver still regard SFP as
> unplugged, issue the module softint before issuing LSC interrupt.
TODO: Reduce duplicated code.
USB xfer callbacks already run in softint context at IPL_SOFTSERIAL,
and I see no reason why the call to psignal must happen instead at
the lower priority of IPL_SOFTCLOCK, so let's avoid using up the
scarce resource of softints for something that doesn't need 'em.
While here, use atomic_store_relaxed to update sc->sc_async and
atomic_load_relaxed to optimisitcally test it without acquiring
proc_lock.
This matches Linux, which also advertises the same semantics and
fails to implement it, according to:
https://man7.org/linux/man-pages/man2/fcntl.2.html
(At what point should we collectively stop advertising the semantics
that doesn't work and call the bug a feature?)
- uhidev API rules:
1. Call uhidev_open when you want exclusive use of a report id.
After it succeeds, you will get interrupts.
2. Call uhidev_close when done with exclusive use of a report id.
After it returns, you will no longer get interrupts.
=> uhidev_open/close do not nest.
3. uhidev_write no longer requires the caller to have exclusive
access -- if there is a write in progress, it will block
interruptibly until done. This way drivers for individual
report ids need not work separately to coordinate their writes.
4. You must uhidev_stop to abort any pending writes on the same
report id. (uhidev_stop no longer does anything else -- to
ensure no more interrupts, just use uhidev_close.)
- Fix uhidev_open/close locking -- uhidev now has an interruptible
config lock held only on first open and last close by any report id
in the device, to serialize the transition between zero and nonzero
numbers of references which requires opening/closing pipes and
allocating/freeing buffers.
- Make /dev/uhidN selnotify(POLLHUP) when the device is yanked.
- Factor uhid device lookup and reference counting and dying
detection and so on into uhid_enter/exit.
- Nix struct uhid_softc::sc_access_lock. This served no purpose but
to confuse me when trying to understand the logic of this beast
(and to ensure uhidev_write exclusion, but it was uninterruptible,
which is wrong for something that implements userland operations,
and didn't actually work because uhidev_write did nothing to
coordinate between different report ids).
- Fix locking in select/poll.
- Use atomics to manage UHID_IMMED to keep it simple. (sc_lock would
be fine too but it makes the code more verbose.)
- Omit needless UHID_ASLP -- cv_broadcast already has this
micro-optimization.
With these changes, my Pinebook survives
for i in `jot 100`; do
echo '###' $i
for j in `jot 16`; do
usbhidctl -rf /dev/uhid$j >/dev/null &
done
wait
done
while plugging and unplugging uhid(4) devices (U2F keys), and the U2F
keys still work as U2F keys.
ok nick, mrg
XXX pullup-9
XXX pullup-8?
Note on ABI and pullups: This changes the layout of struct
uhidev_softc, but with the sole exception of ucycom(4) -- which at
the moment is completely broken and unusable -- the only members that
USB HID drivers use are sc_udev and sc_iface, which haven't changed.
The layout of struct uhidev, which is allocated by each USB HID
driver in its own softc structure, is unchanged.
Calling CachedDir_Assign requires that the variable be initialized. On
most systems, NULL is represented as all-zero bits already. This change
is only for the few other systems.
Add some comments explaining the implementation of Dir_AddDir since that
is tricky to read from the code alone.
Previously, the reference count for a newly created CacheDir had been
set to 1 in CacheNewDir. This was wrong because at that point, the
object had not been referenced by any nonlocal variable. The reference
count is no longer incremented at this point.
All callers of CacheNewDir either append the newly created CachedDir to
a SearchPath via Lst_Append and CachedDir_Ref, or they assign it to a
global variable via CachedDir_Assign.
Since the reference count is no longer wrongly incremented, it does not
need to be decremented more than necessary in Dir_End. To keep the code
simple and maintainable, all assignments to global variables are now
handled by CachedDir_Assign. Adding a CachedDir to a list is still done
manually via Lst_Append, and the corresponding code for decrementing is
in SearchPath_Clean and SearchPath_Free. These details may be cleaned
up in a follow-up commit.
As a result, when OpenDirs_Done is called in the unit tests, the list of
open directories is empty. It had been non-empty in a single unit test
before (dep-wildcards.mk), as a result of calling Dir_Expand.
The additional debug logging for the reference counting is not enabled
by default since it contains memory addresses, which makes the output
dependent on the memory allocator.
The function CachedDir_Destroy has been merged into CachedDir_Undef,
which had only been used in Dir_End before. The new name emphasizes
that it corresponds to CachedDir_Ref.
The memory management for dotLast is quite simple. It is initialized
exactly once main_Init > Init_Objdir > Dir_InitDir and freed exactly
once in main_CleanUp > Dir_End. Previously, dotLast was not freed at all.
The first call to CachedDir_Unref decremented the refCount to 0 but
didn't free anything. Next, CachedDir_Destroy was called, which
decremented the reference count to -1, therefore skipping the actual
freeing. This was probably an implementation mistake.
Since Dir_End is called at the very end of main_CleanUp, no code
accesses dotLast after it has been freed.
In a makefile with repeated ".CURDIR=." lines, Dir_AddDir is called with
a NULL path, once per line. Since the path is NULL, the search for
OpenDirs_Find is skipped and the directory is always read from disk.
The freshly read directory has a refCount of 1, and the refCount never
raises above 2.
In Dir_InitCur, the directory of the previous .CURDIR has a refCount of
2, which is decremented twice and then freed. After this, the new
directory is placed in the global 'cur', after incrementing its refCount
to 2.
It still seems wrong that the refCount of 'cur' is 2 instead of 1, but
it works well.