apparently, there are some issues with linux 2.6 and pearpc.. so i still cant
get the gentoo ppc to start properly. i thought i’d do some studying in the
meantime..
typedef struct {
volatile unsigned int slock;
} raw_spinlock_t;
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{ asm volatile(\"\n1:\t\"
LOCK_PREFIX \" ; decb %0\n\t\"
\"jns 3f\n\"
\"2:\t\"
\"rep;nop\n\t\"
\"cmpb $0,%0\n\t\"
\"jle 2b\n\t\"
\"jmp 1b\n\"
\"3:\n\t\"
: \"+m\" (lock->slock) : : \"memory\");
}
interpretation of the extended inline asm:
1) : “+m” (locl->slock)
“+m” means that the memory operand ‘lock->slock’ is both input and output.
2) : “memory”
from gcc manual:
If your assembler instructions access memory in an unpredictable
fashion, add `memory’ to the list of clobbered registers. This will
cause GCC to not keep memory values cached in registers across the
assembler instruction and not optimize stores or loads to that memory.
3) LOCK_PREFIX is defined at /usr/src/linux/include/asm/alternative.h:
#define LOCK_PREFIX \
\".section .smp_locks,\\"a\\"\n\" \ ; push current section and change section to .smp_locks
\" .align 4\n\" \ ; align to 4 bytes
\" .long 661f\n\" /* address */ \ ; create an entry in the up/smp alternative locking table
\".previous\n\" \ ; pop back the old section
\"661:\n\tlock; \" ; assert processor LOCK# signal
LOCK_PREFIX is supposed to be called within the context of a procedure (executable) which finds its way to a .text section.
i haven’t digged down deep into the internals of ‘alternatives’ yet, but a quick look at kernel/alternative.c :: alternatives_smp_unlock() shows that it’s employing a self modifying code that patches the “lock” instruction with an architecture specific NOP opcode.
without all the extended asm semantics above, the asm roughly translates to:
1: lock ; decrement atomically
decb %0 ; really decrement now..
jns 3f ; successful in acquiring lock?
2: rep ; nothing
nop ; nothing
cmpb $0, %0 ; someone must release the lock first.
jle 2b ; busy wait...
jmp 1b ; lock available! try acquiring lock again.
3: ; exit __raw_spin_lock()
and then comes the trylock variant
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
char oldval;
asm volatile(
\"xchgb %b0,%1\"
:\"=q\" (oldval), \"+m\" (lock->slock)
:\"0\" (0) : \"memory\");
return oldval > 0;
}
interpretation of the extended inline asm:
1) : “=q” (oldval)
output oldval in any a,b,c or d register.
2) : “+m” (locl->slock)
“+m” means that the memory operand ‘lock->slock’ is both input and output.
3) : “0″ (0)
%0 matches the output register for oldval. initialize that with the value 0.
4) : “memory”
from gcc manual:
If your assembler instructions access memory in an unpredictable
fashion, add `memory’ to the list of clobbered registers. This will
cause GCC to not keep memory values cached in registers across the
assembler instruction and not optimize stores or loads to that memory.
__raw_spin_trylock() basically exchanges the current value in raw_spinlock_t->slock with zero and returns true if locking was successful and false if acquiring of lock didn’t succeed.
lastly, we have the raw unlock procedure:
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
char oldval = 1;
asm volatile(\"xchgb %b0, %1\"
: \"=q\" (oldval), \"+m\" (lock->slock)
: \"0\" (oldval) : \"memory\");
}
i haven’t been able to understand the significance of the “%b” in the assembler template but looking at the asm listing of the template with and without the %b yielded the same intructions, so could anyone shed some light on this one?
basically looks like __raw_spin_trylock(), but the difference is that oldval is now initialized to 1 instead of 0.
there are many variants stemming from the idea of this implementation. raw reader/writer locks which allows multiple readers but only one writer (with no concurrent readers). and then there’s the spinlock layer above the raw spinlock implementation.. but those are for another post.
’til then.
June 28, 2008 04:04 AM :: Zamboanga, Philippines 

spiderfetch was driven completely by impulse. The original idea was to get rid of awkward, one-time grep/sed/awk parsing to extract urls from web pages. Then came the impulse “hey, it took so much work to get this working well, why not make it recursive at little added effort”. And from there on countless more impulses happened, to the point that it would be a challenge to recreate the thought process from there to here.

To make filetype detection work, we have to be able to do more than just start a download and wait until it’s done. spiderfetch has a completely new fetcher in pure python (no more calling wget). The fetcher is actually the whole reason why the switch to python happened in the first place. I was looking through the ruby documentation in terms of what I needed from the library and I soon realized it wasn’t cutting it. The http stuff was just too puny. I looked up the same topic in the python docs and immediately realized that it will support what I want to do. In retrospect, the python urllib/httplib library has covered me very well.









And if you have introduced changes that you think would benefit the project you can send people (e.g. the original project owner) a “pull-request”. The recipient can then easily fetch/merge your changes into his project. It really doesn’t get much easier to contribute to (open-source) projects. I certainly did for the first time ;)
Comments can be made on specific lines in a commit (or on the whole commit), which is a great feature (think of it as the equivalent to patches being discussed line-by-line in mailing-lists). I still prefer mails though ;)








