+#else /* ... can't use atomics. */
+/* Implement in terms of three variables.
+ Another option would be to use local_irq_save/restore. */
+
+typedef struct
+{
+ /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
+ unsigned long v[3];
+} local_t;
+
+#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
+
+#define LOCAL_INIT(i) { { (i), 0, 0 } }
+
+static inline unsigned long local_read(local_t *l)
+{
+ return l->v[0] + l->v[1] + l->v[2];
+}
+
+static inline void local_set(local_t *l, unsigned long v)
+{
+ l->v[0] = v;
+ l->v[1] = l->v[2] = 0;
+}
+
+static inline void local_inc(local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l)++;
+ preempt_enable();
+}
+
+static inline void local_dec(local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l)--;
+ preempt_enable();
+}
+
+static inline void local_add(unsigned long v, local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l) += v;
+ preempt_enable();
+}
+
+static inline void local_sub(unsigned long v, local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l) -= v;
+ preempt_enable();
+}
+
+/* Non-atomic variants, ie. preemption disabled and won't be touched
+ * in interrupt, etc. Some archs can optimize this case well. */
+#define __local_inc(l) ((l)->v[0]++)
+#define __local_dec(l) ((l)->v[0]--)
+#define __local_add(i,l) ((l)->v[0] += (i))
+#define __local_sub(i,l) ((l)->v[0] -= (i))
+
+#endif /* Non-atomic implementation */
+