From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by dpdk.org (Postfix, from userid 33) id 0F0445F3B; Tue, 30 Apr 2019 08:51:45 +0200 (CEST) From: bugzilla@dpdk.org To: dev@dpdk.org Date: Tue, 30 Apr 2019 06:51:44 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: DPDK X-Bugzilla-Component: other X-Bugzilla-Version: 18.11 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: zhongdahulinfan@163.com X-Bugzilla-Status: CONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: Normal X-Bugzilla-Assigned-To: dev@dpdk.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://bugs.dpdk.org/ Auto-Submitted: auto-generated X-Auto-Response-Suppress: All MIME-Version: 1.0 Subject: [dpdk-dev] [Bug 260] bugDPDK lock-free hash deletion X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 Apr 2019 06:51:45 -0000 https://bugs.dpdk.org/show_bug.cgi?id=3D260 Bug ID: 260 Summary: bugDPDK lock-free hash deletion Product: DPDK Version: 18.11 Hardware: All OS: All Status: CONFIRMED Severity: normal Priority: Normal Component: other Assignee: dev@dpdk.org Reporter: zhongdahulinfan@163.com Target Milestone: --- lock-free=E7=89=88=E6=9C=AC=E7=9A=84=E5=93=88=E5=B8=8C=E8=A1=A8=EF=BC=8C=E5= =9C=A8=E5=88=9B=E5=BB=BA=E7=9A=84=E6=97=B6=E5=80=99=E6=8C=87=E5=AE=9A=E4=BA= =86flag=EF=BC=9A RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF | RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_= ADD =E4=BB=A5=E4=BD=BF=E5=93=88=E5=B8=8C=E8=A1=A8=E6=94=AF=E6=8C=81multi-writer= =EF=BC=8CRTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD=E6=A0=87=E8=AE=B0=E4=BD=BF= =E5=BE=97=E6=AF=8F=E4=B8=AAlcore=E9=83=BD=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94= =A8local cache=E5=88=86=E9=85=8Dkey slot=EF=BC=9A struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params) { ... if (params->extra_flag & RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD) { use_local_cache =3D 1; writer_takes_lock =3D 1; } ... /* Store all keys and leave the first entry as a dummy entry for lookup_bulk */ if (use_local_cache) /* * Increase number of slots by total number of indices * that can be stored in the lcore caches * except for the first cache */ num_key_slots =3D params->entries + (RTE_MAX_LCORE - 1) * (LCORE_CACHE_SIZE - 1) + 1; else num_key_slots =3D params->entries + 1; ... } =E8=BF=99=E4=B9=88=E5=81=9A=E7=9A=84=E5=A5=BD=E5=A4=84=E6=98=AF=EF=BC=8C=E6= =AF=8F=E4=B8=AA=E5=86=99=E8=80=85=E5=8F=AF=E4=BB=A5=E4=BB=8E=E6=9C=AC=E5=9C= =B0cache=E5=88=86=E9=85=8Dkey slot=EF=BC=8C=E5=8F=AF=E5=87=8F=E5=B0=91cache= miss=EF=BC=8C=E6=8F=90=E5=8D=87=E5=93=88=E5=B8=8C=E6=8F=92=E5=85=A5=E7=9A= =84=E6=80=A7=E8=83=BD=E3=80=82 =E8=BF=99=E9=87=8C=E8=A6=81=E5=85=88=E8=AF=B4=E4=B8=80=E4=B8=8Brte_hash=E7= =9A=84key=E5=92=8Cdata=E7=9A=84=E5=AD=98=E5=82=A8=E7=9A=84=E7=BB=93=E6=9E= =84=EF=BC=9A | dummy | pdata + key | pdata + key | pdata + key | pdata + key | pdata += key | pdata + key | pdata + key | pdata + key |... 0 | 1 2 3=20= =20=20=20=20=20=20 4 5 6=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 7 8 | | <--------------=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20 bucket=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 ----------> | struct rte_hash=E9=87=8C=E7=9A=84=E6=88=90=E5=91=98key_store=E5=B0=B1=E6=98= =AF=E4=B8=8A=E8=BF=B0=E6=95=B0=E7=BB=84=EF=BC=8C=E5=AD=98=E6=94=BEkey=E7=9A= =84=E5=86=85=E5=AE=B9=E5=92=8Cdata=E6=8C=87=E9=92=88=EF=BC=8C=E5=85=B6=E4= =B8=AD index 0=E6=B2=A1=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC=8C=E6=9C=89=E6=95= =88=E6=95=B0=E6=8D=AE=E4=BB=8Eindex 1 =E5=BC=80=E5=A7=8B=E3=80=82=E8=AF=A5=E6=95=B0=E7=BB=84=E8=A2=AB=E5=88=92=E5= =88=86=E6=88=90=E8=8B=A5=E5=B9=B2=E4=B8=AAbucket=EF=BC=8C=E6=AF=8F=E4=B8=AA= bucket=E7=9A=84=E5=A4=A7=E5=B0=8F=E4=B8=BA8=E3=80=82=E8=BF=99=E4=B9=88=E5= =81=9A=E6=98=AF=E6=9C=89=E5=8E=9F=E5=9B=A0=E7=9A=84=EF=BC=8Crte_hash=E4=BD= =BF=E7=94=A8cuckoo =E5=93=88=E5=B8=8C=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=BC=95=E5=85=A5bucket=E8=A7= =A3=E5=86=B3=E5=93=88=E5=B8=8C=E5=86=B2=E7=AA=81=EF=BC=8C=E8=80=8C=E9=9D=9E= =E5=BC=80=E9=93=BE=E3=80=82=E4=BB=A5=E5=86=99=E4=B8=BA=E4=BE=8B=EF=BC=8C=E5= =9C=A8=E5=86=99=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84=E6=97=B6=E5=80=99=EF=BC= =8C=E5=85=88=E5=93=88=E5=B8=8C=E5=88=B0primary bucket=EF=BC=8C=E5=86=8D=E5=BE=AA=E7=8E=AF=E9=81=8D=E5=8E=86=E8=AF=A5bucket= =E6=89=BE=E5=88=B0=E5=AD=98=E5=82=A8=E4=BD=8D=E7=BD=AE=EF=BC=8C=E5=A6=82=E8= =8B=A5=E6=9C=89=E7=A9=BA=E4=BD=8D=E5=88=99=E6=8F=92=E5=85=A5=EF=BC=8C=E5=90= =A6=E5=88=99=E7=BB=A7=E7=BB=AD=E6=89=BEsecondary bucket=E3=80=82 =E7=BB=93=E6=9E=84=E4=BD=93=E5=AE=9A=E4=B9=89=E5=A6=82=E4=B8=8B=EF=BC=9A /* Structure that stores key-value pair */ struct rte_hash_key { union { uintptr_t idata; void *pdata; }; /* Variable key size */ char key[0]; }; /** Bucket structure */ struct rte_hash_bucket { uint16_t sig_current[RTE_HASH_BUCKET_ENTRIES]; uint32_t key_idx[RTE_HASH_BUCKET_ENTRIES]; uint8_t flag[RTE_HASH_BUCKET_ENTRIES]; void *next; } __rte_cache_aligned; =E7=84=B6=E5=90=8E=E8=BF=99=E4=BA=9Bkey index=EF=BC=8C=E7=94=A8=E4=B8=80=E4= =B8=AArte_ring=E6=9D=A5=E5=AD=98=E5=82=A8=EF=BC=9A struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params) { ... /* Populate free slots ring. Entry zero is reserved for key misses. */ for (i =3D 1; i < num_key_slots; i++) rte_ring_sp_enqueue(r, (void *)((uintptr_t) i)); ... } =E5=BD=93=E4=BD=BF=E7=94=A8lock-free=E5=93=88=E5=B8=8C=E8=A1=A8=E6=97=B6=EF= =BC=8C=E5=88=A0=E9=99=A4=E4=B8=80=E4=B8=AA=E8=A1=A8=E9=A1=B9=E7=9A=84=E6=97= =B6=E5=80=99key=E5=92=8Cvalue=E9=87=87=E7=94=A8=E5=BB=B6=E5=90=8E=E5=9B=9E= =E6=94=B6=E5=86=85=E5=AD=98=E7=9A=84=E7=AD=96=E7=95=A5=EF=BC=8C=E4=BD=BF=E5= =BE=97multi-readers=E8=AE=BF=E9=97=AE=E5=93=88=E5=B8=8C=E8=A1=A8=E4=B8=8D= =E9=9C=80=E8=A6=81=E5=8A=A0=E9=94=81=EF=BC=8C=E5=A4=A7=E5=A4=A7=E5=87=8F=E5= =B0=91=E5=A4=9A=E6=A0=B8=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F=E7=9A=84=E6=80= =A7=E8=83=BD=E6=8D=9F=E8=80=97=E3=80=82=E6=88=91=E4=BB=AC=E8=B0=83=E7=94=A8= dpdk API rte_hash_del_key_xxx=E5=88=A0=E9=99=A4=E8=A1=A8=E9=A1=B9=E6=97=B6=EF=BC= =8C=E5=8F=AA=E5=B0=86=E8=A1=A8=E9=A1=B9=E4=BB=8E=E5=93=88=E5=B8=8C=E8=A1=A8= =E4=B8=AD=E6=91=98=E9=99=A4=EF=BC=8C=E8=BF=94=E5=9B=9E=E4=B8=80=E4=B8=AAkey= =E7=9A=84=E5=AD=98=E5=82=A8=E4=BD=8D=E7=BD=AEposition=EF=BC=8C=E5=B0=B1=E6= =98=AF=E4=B8=8A=E8=BF=B0=E6=89=80=E8=AF=B4=E7=9A=84key index=EF=BC=8C=E7=84=B6=E5=90=8E=E5=9C=A8=E6=89=80=E6=9C=89=E5=BC=95=E7=94= =A8=E8=AF=A5=E8=A1=A8=E9=A1=B9=E7=9A=84readers/writers=E9=83=BD=E9=80=80=E5= =87=BA=E5=BC=95=E7=94=A8=E5=90=8E=EF=BC=8C=E5=86=8D=E6=A0=B9=E6=8D=AEpositi= on=E5=9B=9E=E6=94=B6key=E5=92=8Cvalue=E7=9A=84=E5=AD=98=E5=82=A8=E7=A9=BA= =E9=97=B4=E3=80=82key=E7=9A=84=E5=9B=9E=E6=94=B6=E8=B0=83=E7=94=A8=E4=B8=80= =E4=B8=8B=E6=8E=A5=E5=8F=A3=EF=BC=9A int __rte_experimental rte_hash_free_key_with_position(const struct rte_hash *h, const int32_t position) { RETURN_IF_TRUE(((h =3D=3D NULL) || (position =3D=3D EMPTY_SLOT)), -EINV= AL); unsigned int lcore_id, n_slots; struct lcore_cache *cached_free_slots; const int32_t total_entries =3D h->num_buckets * RTE_HASH_BUCKET_ENTRIE= S; /* Out of bounds */ if (position >=3D total_entries) return -EINVAL; if (h->use_local_cache) { lcore_id =3D rte_lcore_id(); cached_free_slots =3D &h->local_free_slots[lcore_id]; /* Cache full, need to free it. */ if (cached_free_slots->len =3D=3D LCORE_CACHE_SIZE) { /* Need to enqueue the free slots in global ring. */ n_slots =3D rte_ring_mp_enqueue_burst(h->free_slots, cached_free_slots->objs, LCORE_CACHE_SIZE, NULL); cached_free_slots->len -=3D n_slots; } /* Put index of new free slot in cache. */ cached_free_slots->objs[cached_free_slots->len] =3D (void *)((uintptr_t)position); cached_free_slots->len++; } else { rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)position)); } return 0; } =E4=BB=94=E7=BB=86=E7=9C=8Brte_hash=E7=9A=84=E5=AE=9E=E7=8E=B0=EF=BC=8C=E4= =B8=8D=E9=9A=BE=E5=8F=91=E7=8E=B0=E4=B8=8A=E8=BF=B0=E5=87=BD=E6=95=B0=E6=9C= =89=E4=B8=A4=E4=B8=AA=E5=9C=B0=E6=96=B9=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98= =EF=BC=9A 1=E3=80=81"Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91 =E8=BF=99=E4=B8=AA "Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9=80=BB=E8= =BE=91=EF=BC=8C=E5=9C=A8=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84use_local_cache= =E6=A0=87=E8=AF=86=E6=B2=A1=E8=A2=AB=E7=BD=AE=E4=B8=BA=E7=9A=84=E6=97=B6=E5= =80=99=E6=98=AF=E6=88=90=E7=AB=8B=E7=9A=84=EF=BC=8Ckey index=E7=9A=84=E6=95=B0=E9=87=8F=E6=81=B0=E5=A5=BD=E6=98=AF=E5=93=88=E5=B8= =8C=E8=A1=A8entries=E7=9A=84=E6=95=B0=E9=87=8F=E3=80=82=E4=BD=86=E5=BD=93us= e_local_cache=E4=B8=BA=E7=9C=9F=E6=97=B6=EF=BC=8C=E5=AE=83=E5=B0=B1=E4=B8= =8D=E6=AD=A3=E7=A1=AE=E4=BA=86=E3=80=82=E5=9B=9E=E7=9C=8B=E4=B8=80=E4=B8=8B= =E5=88=9B=E5=BB=BA=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84=E5=87=BD=E6=95=B0rte= _hash_create=EF=BC=8C=E5=85=B6=E4=B8=ADkey slots=E7=9A=84=E8=AE=A1=E7=AE=97=EF=BC=9A /* Store all keys and leave the first entry as a dummy entry for lookup_bul= k */ if (use_local_cache) /* * Increase number of slots by total number of indices * that can be stored in the lcore caches * except for the first cache */ num_key_slots =3D params->entries + (RTE_MAX_LCORE - 1) * (LCORE_CACHE_SIZE - 1) + 1; else num_key_slots =3D params->entries + 1; =E8=BF=99=E6=97=B6=E5=80=99=E9=99=A4=E4=BA=86=E5=88=86=E9=85=8Dentries=E4= =B8=AAkey=E5=86=85=E5=AD=98=E7=A9=BA=E9=97=B4=EF=BC=8C=E8=BF=98=E8=A6=81=E7= =BB=99=E6=AF=8F=E4=B8=AAlcore=E5=88=86=E9=85=8DLCORE_CACHE_SIZE=E6=95=B0=E9= =87=8F=E7=9A=84key=E7=A9=BA=E9=97=B4=EF=BC=8C=E9=82=A3=E4=B9=88=E6=AD=A4=E6= =97=B6key=E7=9A=84=E6=95=B0=E9=87=8F=E6=98=AF=E4=BC=9A=E5=A4=A7=E4=BA=8E=E5= =93=88=E5=B8=8C=E8=A1=A8=E7=9A=84total entry=E7=9A=84=EF=BC=8C=E6=89=80=E4=BB=A5 rte_hash_free_key_with_position= =E7=9A=84"Out of bounds"=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91=E6=9C=89=E8=AF= =AF=E3=80=82 2=E3=80=81position=E5=8F=82=E6=95=B0=E9=97=AE=E9=A2=98 position=E6=98=AFrte_hash_del_key_xxx()=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC= =EF=BC=8C=E4=B8=BA (key_idx - 1)=E3=80=82=E5=89=8D=E9=9D=A2=E8=AF=B4=E8=BF= =87key=E7=9A=84index 0=E6=9C=AA=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC=8C=E4=BB=8E1=E5=BC=80=E5=A7=8B= =E6=9C=89=E6=95=88=E3=80=82=E9=82=A3=E4=B9=88=E7=9B=B4=E6=8E=A5=E5=B0=86pos= ition enqueue=E5=88=B0free_slot=E9=98=9F=E5=88=97=E6=98=AF=E4=B8=8D=E6=AD= =A3=E7=A1=AE=E7=9A=84=EF=BC=9A rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)position)); =E8=BF=99=E4=BC=9A=E5=AF=BC=E8=87=B4ring=E9=98=9F=E5=88=97=E9=87=8C=E5=8F= =AF=E8=83=BD=E5=AD=98=E5=9C=A8=E5=A4=9A=E4=B8=AA=E5=80=BC=E4=B8=BA0=E7=9A= =84position=EF=BC=8C=E4=BB=8E=E8=80=8C=E6=8D=9F=E5=9D=8Fring=E9=98=9F=E5=88= =97=E3=80=82=E4=BB=A5ring=E7=9A=84size=E6=98=AF4=E4=B8=BA=E4=BE=8B=EF=BC=9A ring=E5=88=9D=E5=A7=8B=E7=8A=B6=E6=80=81=EF=BC=9A |1 | 2 | 3 | 4 | dequeue=E5=AE=8C=E6=89=80=E6=9C=89key_idx=E5=90=8E=EF=BC=8C=E8=BF=94=E5=9B= =9Eposition=E4=B8=BA 0,1,2,3=EF=BC=8C=E5=86=8Denqueue=E5=9B=9Ering=E9=98=9F= =E5=88=97 =E4=B8=80=E8=B6=9Fdequeue enqueue=E8=BF=87=E5=90=8E=EF=BC=9A | 0 | 1 | 2 | 3 | dequeue=E5=AE=8C=E6=89=80=E6=9C=89key_idx=E5=90=8E=EF=BC=8C=E8=BF=94=E5=9B= =9Eposition=E4=B8=BA 0,1,2=EF=BC=88=E5=85=B6=E4=B8=ADkey_idx 0=E6=98=AF=E6= =97=A0=E6=95=88=E7=9A=84=EF=BC=8C=E4=B8=8D=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC= =89=EF=BC=8C=E5=86=8Denqueue=E5=9B=9Ering=E9=98=9F=E5=88=97 =E4=B8=A4=E8=B6=9Fdequeue enqueue=E8=BF=87=E5=90=8E=EF=BC=9A | 0 | 0 | 1 | 2 | =E5=AF=B9=E6=AF=94=E9=9D=9Elock-free=E7=9A=84key=E5=9B=9E=E6=94=B6=E6=8E=A5= =E5=8F=A3=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=8F=91=E7=8E=B0=EF=BC=8Cremove_entry= ()=E6=98=AF=E7=9B=B4=E6=8E=A5=E5=B0=86key_indx=E5=85=A5=E9=98=9F=E7=9A=84= =EF=BC=8C=E6=89=80=E4=BB=A5=E4=B8=8D=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98=EF= =BC=9A static inline void remove_entry(const struct rte_hash *h, struct rte_hash_bucket *bkt, unsigne= d i) { unsigned lcore_id, n_slots; struct lcore_cache *cached_free_slots; if (h->use_local_cache) { lcore_id =3D rte_lcore_id(); cached_free_slots =3D &h->local_free_slots[lcore_id]; /* Cache full, need to free it. */ if (cached_free_slots->len =3D=3D LCORE_CACHE_SIZE) { /* Need to enqueue the free slots in global ring. */ n_slots =3D rte_ring_mp_enqueue_burst(h->free_slots, cached_free_slots->objs, LCORE_CACHE_SIZE, NULL); cached_free_slots->len -=3D n_slots; } /* Put index of new free slot in cache. */ cached_free_slots->objs[cached_free_slots->len] =3D (void *)((uintptr_t)bkt->key_idx[i]); cached_free_slots->len++; } else { rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)bkt->key_idx[i])); } } =E4=BF=AE=E5=A4=8D=E6=96=B9=E6=B3=95 1=E3=80=81=E4=BF=AE=E6=94=B9"Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9= =80=BB=E8=BE=91 2=E3=80=81position=E5=9C=A8enqueue=E5=9B=9Efree_slots=E9=98=9F=E5=88=97=E4= =B9=8B=E5=89=8D=E5=8A=A01 --=20 You are receiving this mail because: You are the assignee for the bug.= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by dpdk.space (Postfix) with ESMTP id 7B82EA0679 for ; Tue, 30 Apr 2019 08:51:48 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id C92F15942; Tue, 30 Apr 2019 08:51:46 +0200 (CEST) Received: by dpdk.org (Postfix, from userid 33) id 0F0445F3B; Tue, 30 Apr 2019 08:51:45 +0200 (CEST) From: bugzilla@dpdk.org To: dev@dpdk.org Date: Tue, 30 Apr 2019 06:51:44 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: DPDK X-Bugzilla-Component: other X-Bugzilla-Version: 18.11 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: zhongdahulinfan@163.com X-Bugzilla-Status: CONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: Normal X-Bugzilla-Assigned-To: dev@dpdk.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://bugs.dpdk.org/ Auto-Submitted: auto-generated X-Auto-Response-Suppress: All MIME-Version: 1.0 Subject: [dpdk-dev] [Bug 260] bugDPDK lock-free hash deletion X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Message-ID: <20190430065144.Sf1zWCGypeFNjYeNJ0o-mTfx4FI4dUB-ZbjyhxM_hdw@z> https://bugs.dpdk.org/show_bug.cgi?id=3D260 Bug ID: 260 Summary: bugDPDK lock-free hash deletion Product: DPDK Version: 18.11 Hardware: All OS: All Status: CONFIRMED Severity: normal Priority: Normal Component: other Assignee: dev@dpdk.org Reporter: zhongdahulinfan@163.com Target Milestone: --- lock-free=E7=89=88=E6=9C=AC=E7=9A=84=E5=93=88=E5=B8=8C=E8=A1=A8=EF=BC=8C=E5= =9C=A8=E5=88=9B=E5=BB=BA=E7=9A=84=E6=97=B6=E5=80=99=E6=8C=87=E5=AE=9A=E4=BA= =86flag=EF=BC=9A RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF | RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_= ADD =E4=BB=A5=E4=BD=BF=E5=93=88=E5=B8=8C=E8=A1=A8=E6=94=AF=E6=8C=81multi-writer= =EF=BC=8CRTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD=E6=A0=87=E8=AE=B0=E4=BD=BF= =E5=BE=97=E6=AF=8F=E4=B8=AAlcore=E9=83=BD=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94= =A8local cache=E5=88=86=E9=85=8Dkey slot=EF=BC=9A struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params) { ... if (params->extra_flag & RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD) { use_local_cache =3D 1; writer_takes_lock =3D 1; } ... /* Store all keys and leave the first entry as a dummy entry for lookup_bulk */ if (use_local_cache) /* * Increase number of slots by total number of indices * that can be stored in the lcore caches * except for the first cache */ num_key_slots =3D params->entries + (RTE_MAX_LCORE - 1) * (LCORE_CACHE_SIZE - 1) + 1; else num_key_slots =3D params->entries + 1; ... } =E8=BF=99=E4=B9=88=E5=81=9A=E7=9A=84=E5=A5=BD=E5=A4=84=E6=98=AF=EF=BC=8C=E6= =AF=8F=E4=B8=AA=E5=86=99=E8=80=85=E5=8F=AF=E4=BB=A5=E4=BB=8E=E6=9C=AC=E5=9C= =B0cache=E5=88=86=E9=85=8Dkey slot=EF=BC=8C=E5=8F=AF=E5=87=8F=E5=B0=91cache= miss=EF=BC=8C=E6=8F=90=E5=8D=87=E5=93=88=E5=B8=8C=E6=8F=92=E5=85=A5=E7=9A= =84=E6=80=A7=E8=83=BD=E3=80=82 =E8=BF=99=E9=87=8C=E8=A6=81=E5=85=88=E8=AF=B4=E4=B8=80=E4=B8=8Brte_hash=E7= =9A=84key=E5=92=8Cdata=E7=9A=84=E5=AD=98=E5=82=A8=E7=9A=84=E7=BB=93=E6=9E= =84=EF=BC=9A | dummy | pdata + key | pdata + key | pdata + key | pdata + key | pdata += key | pdata + key | pdata + key | pdata + key |... 0 | 1 2 3=20= =20=20=20=20=20=20 4 5 6=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 7 8 | | <--------------=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20 bucket=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 ----------> | struct rte_hash=E9=87=8C=E7=9A=84=E6=88=90=E5=91=98key_store=E5=B0=B1=E6=98= =AF=E4=B8=8A=E8=BF=B0=E6=95=B0=E7=BB=84=EF=BC=8C=E5=AD=98=E6=94=BEkey=E7=9A= =84=E5=86=85=E5=AE=B9=E5=92=8Cdata=E6=8C=87=E9=92=88=EF=BC=8C=E5=85=B6=E4= =B8=AD index 0=E6=B2=A1=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC=8C=E6=9C=89=E6=95= =88=E6=95=B0=E6=8D=AE=E4=BB=8Eindex 1 =E5=BC=80=E5=A7=8B=E3=80=82=E8=AF=A5=E6=95=B0=E7=BB=84=E8=A2=AB=E5=88=92=E5= =88=86=E6=88=90=E8=8B=A5=E5=B9=B2=E4=B8=AAbucket=EF=BC=8C=E6=AF=8F=E4=B8=AA= bucket=E7=9A=84=E5=A4=A7=E5=B0=8F=E4=B8=BA8=E3=80=82=E8=BF=99=E4=B9=88=E5= =81=9A=E6=98=AF=E6=9C=89=E5=8E=9F=E5=9B=A0=E7=9A=84=EF=BC=8Crte_hash=E4=BD= =BF=E7=94=A8cuckoo =E5=93=88=E5=B8=8C=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=BC=95=E5=85=A5bucket=E8=A7= =A3=E5=86=B3=E5=93=88=E5=B8=8C=E5=86=B2=E7=AA=81=EF=BC=8C=E8=80=8C=E9=9D=9E= =E5=BC=80=E9=93=BE=E3=80=82=E4=BB=A5=E5=86=99=E4=B8=BA=E4=BE=8B=EF=BC=8C=E5= =9C=A8=E5=86=99=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84=E6=97=B6=E5=80=99=EF=BC= =8C=E5=85=88=E5=93=88=E5=B8=8C=E5=88=B0primary bucket=EF=BC=8C=E5=86=8D=E5=BE=AA=E7=8E=AF=E9=81=8D=E5=8E=86=E8=AF=A5bucket= =E6=89=BE=E5=88=B0=E5=AD=98=E5=82=A8=E4=BD=8D=E7=BD=AE=EF=BC=8C=E5=A6=82=E8= =8B=A5=E6=9C=89=E7=A9=BA=E4=BD=8D=E5=88=99=E6=8F=92=E5=85=A5=EF=BC=8C=E5=90= =A6=E5=88=99=E7=BB=A7=E7=BB=AD=E6=89=BEsecondary bucket=E3=80=82 =E7=BB=93=E6=9E=84=E4=BD=93=E5=AE=9A=E4=B9=89=E5=A6=82=E4=B8=8B=EF=BC=9A /* Structure that stores key-value pair */ struct rte_hash_key { union { uintptr_t idata; void *pdata; }; /* Variable key size */ char key[0]; }; /** Bucket structure */ struct rte_hash_bucket { uint16_t sig_current[RTE_HASH_BUCKET_ENTRIES]; uint32_t key_idx[RTE_HASH_BUCKET_ENTRIES]; uint8_t flag[RTE_HASH_BUCKET_ENTRIES]; void *next; } __rte_cache_aligned; =E7=84=B6=E5=90=8E=E8=BF=99=E4=BA=9Bkey index=EF=BC=8C=E7=94=A8=E4=B8=80=E4= =B8=AArte_ring=E6=9D=A5=E5=AD=98=E5=82=A8=EF=BC=9A struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params) { ... /* Populate free slots ring. Entry zero is reserved for key misses. */ for (i =3D 1; i < num_key_slots; i++) rte_ring_sp_enqueue(r, (void *)((uintptr_t) i)); ... } =E5=BD=93=E4=BD=BF=E7=94=A8lock-free=E5=93=88=E5=B8=8C=E8=A1=A8=E6=97=B6=EF= =BC=8C=E5=88=A0=E9=99=A4=E4=B8=80=E4=B8=AA=E8=A1=A8=E9=A1=B9=E7=9A=84=E6=97= =B6=E5=80=99key=E5=92=8Cvalue=E9=87=87=E7=94=A8=E5=BB=B6=E5=90=8E=E5=9B=9E= =E6=94=B6=E5=86=85=E5=AD=98=E7=9A=84=E7=AD=96=E7=95=A5=EF=BC=8C=E4=BD=BF=E5= =BE=97multi-readers=E8=AE=BF=E9=97=AE=E5=93=88=E5=B8=8C=E8=A1=A8=E4=B8=8D= =E9=9C=80=E8=A6=81=E5=8A=A0=E9=94=81=EF=BC=8C=E5=A4=A7=E5=A4=A7=E5=87=8F=E5= =B0=91=E5=A4=9A=E6=A0=B8=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F=E7=9A=84=E6=80= =A7=E8=83=BD=E6=8D=9F=E8=80=97=E3=80=82=E6=88=91=E4=BB=AC=E8=B0=83=E7=94=A8= dpdk API rte_hash_del_key_xxx=E5=88=A0=E9=99=A4=E8=A1=A8=E9=A1=B9=E6=97=B6=EF=BC= =8C=E5=8F=AA=E5=B0=86=E8=A1=A8=E9=A1=B9=E4=BB=8E=E5=93=88=E5=B8=8C=E8=A1=A8= =E4=B8=AD=E6=91=98=E9=99=A4=EF=BC=8C=E8=BF=94=E5=9B=9E=E4=B8=80=E4=B8=AAkey= =E7=9A=84=E5=AD=98=E5=82=A8=E4=BD=8D=E7=BD=AEposition=EF=BC=8C=E5=B0=B1=E6= =98=AF=E4=B8=8A=E8=BF=B0=E6=89=80=E8=AF=B4=E7=9A=84key index=EF=BC=8C=E7=84=B6=E5=90=8E=E5=9C=A8=E6=89=80=E6=9C=89=E5=BC=95=E7=94= =A8=E8=AF=A5=E8=A1=A8=E9=A1=B9=E7=9A=84readers/writers=E9=83=BD=E9=80=80=E5= =87=BA=E5=BC=95=E7=94=A8=E5=90=8E=EF=BC=8C=E5=86=8D=E6=A0=B9=E6=8D=AEpositi= on=E5=9B=9E=E6=94=B6key=E5=92=8Cvalue=E7=9A=84=E5=AD=98=E5=82=A8=E7=A9=BA= =E9=97=B4=E3=80=82key=E7=9A=84=E5=9B=9E=E6=94=B6=E8=B0=83=E7=94=A8=E4=B8=80= =E4=B8=8B=E6=8E=A5=E5=8F=A3=EF=BC=9A int __rte_experimental rte_hash_free_key_with_position(const struct rte_hash *h, const int32_t position) { RETURN_IF_TRUE(((h =3D=3D NULL) || (position =3D=3D EMPTY_SLOT)), -EINV= AL); unsigned int lcore_id, n_slots; struct lcore_cache *cached_free_slots; const int32_t total_entries =3D h->num_buckets * RTE_HASH_BUCKET_ENTRIE= S; /* Out of bounds */ if (position >=3D total_entries) return -EINVAL; if (h->use_local_cache) { lcore_id =3D rte_lcore_id(); cached_free_slots =3D &h->local_free_slots[lcore_id]; /* Cache full, need to free it. */ if (cached_free_slots->len =3D=3D LCORE_CACHE_SIZE) { /* Need to enqueue the free slots in global ring. */ n_slots =3D rte_ring_mp_enqueue_burst(h->free_slots, cached_free_slots->objs, LCORE_CACHE_SIZE, NULL); cached_free_slots->len -=3D n_slots; } /* Put index of new free slot in cache. */ cached_free_slots->objs[cached_free_slots->len] =3D (void *)((uintptr_t)position); cached_free_slots->len++; } else { rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)position)); } return 0; } =E4=BB=94=E7=BB=86=E7=9C=8Brte_hash=E7=9A=84=E5=AE=9E=E7=8E=B0=EF=BC=8C=E4= =B8=8D=E9=9A=BE=E5=8F=91=E7=8E=B0=E4=B8=8A=E8=BF=B0=E5=87=BD=E6=95=B0=E6=9C= =89=E4=B8=A4=E4=B8=AA=E5=9C=B0=E6=96=B9=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98= =EF=BC=9A 1=E3=80=81"Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91 =E8=BF=99=E4=B8=AA "Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9=80=BB=E8= =BE=91=EF=BC=8C=E5=9C=A8=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84use_local_cache= =E6=A0=87=E8=AF=86=E6=B2=A1=E8=A2=AB=E7=BD=AE=E4=B8=BA=E7=9A=84=E6=97=B6=E5= =80=99=E6=98=AF=E6=88=90=E7=AB=8B=E7=9A=84=EF=BC=8Ckey index=E7=9A=84=E6=95=B0=E9=87=8F=E6=81=B0=E5=A5=BD=E6=98=AF=E5=93=88=E5=B8= =8C=E8=A1=A8entries=E7=9A=84=E6=95=B0=E9=87=8F=E3=80=82=E4=BD=86=E5=BD=93us= e_local_cache=E4=B8=BA=E7=9C=9F=E6=97=B6=EF=BC=8C=E5=AE=83=E5=B0=B1=E4=B8= =8D=E6=AD=A3=E7=A1=AE=E4=BA=86=E3=80=82=E5=9B=9E=E7=9C=8B=E4=B8=80=E4=B8=8B= =E5=88=9B=E5=BB=BA=E5=93=88=E5=B8=8C=E8=A1=A8=E7=9A=84=E5=87=BD=E6=95=B0rte= _hash_create=EF=BC=8C=E5=85=B6=E4=B8=ADkey slots=E7=9A=84=E8=AE=A1=E7=AE=97=EF=BC=9A /* Store all keys and leave the first entry as a dummy entry for lookup_bul= k */ if (use_local_cache) /* * Increase number of slots by total number of indices * that can be stored in the lcore caches * except for the first cache */ num_key_slots =3D params->entries + (RTE_MAX_LCORE - 1) * (LCORE_CACHE_SIZE - 1) + 1; else num_key_slots =3D params->entries + 1; =E8=BF=99=E6=97=B6=E5=80=99=E9=99=A4=E4=BA=86=E5=88=86=E9=85=8Dentries=E4= =B8=AAkey=E5=86=85=E5=AD=98=E7=A9=BA=E9=97=B4=EF=BC=8C=E8=BF=98=E8=A6=81=E7= =BB=99=E6=AF=8F=E4=B8=AAlcore=E5=88=86=E9=85=8DLCORE_CACHE_SIZE=E6=95=B0=E9= =87=8F=E7=9A=84key=E7=A9=BA=E9=97=B4=EF=BC=8C=E9=82=A3=E4=B9=88=E6=AD=A4=E6= =97=B6key=E7=9A=84=E6=95=B0=E9=87=8F=E6=98=AF=E4=BC=9A=E5=A4=A7=E4=BA=8E=E5= =93=88=E5=B8=8C=E8=A1=A8=E7=9A=84total entry=E7=9A=84=EF=BC=8C=E6=89=80=E4=BB=A5 rte_hash_free_key_with_position= =E7=9A=84"Out of bounds"=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91=E6=9C=89=E8=AF= =AF=E3=80=82 2=E3=80=81position=E5=8F=82=E6=95=B0=E9=97=AE=E9=A2=98 position=E6=98=AFrte_hash_del_key_xxx()=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC= =EF=BC=8C=E4=B8=BA (key_idx - 1)=E3=80=82=E5=89=8D=E9=9D=A2=E8=AF=B4=E8=BF= =87key=E7=9A=84index 0=E6=9C=AA=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC=8C=E4=BB=8E1=E5=BC=80=E5=A7=8B= =E6=9C=89=E6=95=88=E3=80=82=E9=82=A3=E4=B9=88=E7=9B=B4=E6=8E=A5=E5=B0=86pos= ition enqueue=E5=88=B0free_slot=E9=98=9F=E5=88=97=E6=98=AF=E4=B8=8D=E6=AD= =A3=E7=A1=AE=E7=9A=84=EF=BC=9A rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)position)); =E8=BF=99=E4=BC=9A=E5=AF=BC=E8=87=B4ring=E9=98=9F=E5=88=97=E9=87=8C=E5=8F= =AF=E8=83=BD=E5=AD=98=E5=9C=A8=E5=A4=9A=E4=B8=AA=E5=80=BC=E4=B8=BA0=E7=9A= =84position=EF=BC=8C=E4=BB=8E=E8=80=8C=E6=8D=9F=E5=9D=8Fring=E9=98=9F=E5=88= =97=E3=80=82=E4=BB=A5ring=E7=9A=84size=E6=98=AF4=E4=B8=BA=E4=BE=8B=EF=BC=9A ring=E5=88=9D=E5=A7=8B=E7=8A=B6=E6=80=81=EF=BC=9A |1 | 2 | 3 | 4 | dequeue=E5=AE=8C=E6=89=80=E6=9C=89key_idx=E5=90=8E=EF=BC=8C=E8=BF=94=E5=9B= =9Eposition=E4=B8=BA 0,1,2,3=EF=BC=8C=E5=86=8Denqueue=E5=9B=9Ering=E9=98=9F= =E5=88=97 =E4=B8=80=E8=B6=9Fdequeue enqueue=E8=BF=87=E5=90=8E=EF=BC=9A | 0 | 1 | 2 | 3 | dequeue=E5=AE=8C=E6=89=80=E6=9C=89key_idx=E5=90=8E=EF=BC=8C=E8=BF=94=E5=9B= =9Eposition=E4=B8=BA 0,1,2=EF=BC=88=E5=85=B6=E4=B8=ADkey_idx 0=E6=98=AF=E6= =97=A0=E6=95=88=E7=9A=84=EF=BC=8C=E4=B8=8D=E8=A2=AB=E4=BD=BF=E7=94=A8=EF=BC= =89=EF=BC=8C=E5=86=8Denqueue=E5=9B=9Ering=E9=98=9F=E5=88=97 =E4=B8=A4=E8=B6=9Fdequeue enqueue=E8=BF=87=E5=90=8E=EF=BC=9A | 0 | 0 | 1 | 2 | =E5=AF=B9=E6=AF=94=E9=9D=9Elock-free=E7=9A=84key=E5=9B=9E=E6=94=B6=E6=8E=A5= =E5=8F=A3=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=8F=91=E7=8E=B0=EF=BC=8Cremove_entry= ()=E6=98=AF=E7=9B=B4=E6=8E=A5=E5=B0=86key_indx=E5=85=A5=E9=98=9F=E7=9A=84= =EF=BC=8C=E6=89=80=E4=BB=A5=E4=B8=8D=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98=EF= =BC=9A static inline void remove_entry(const struct rte_hash *h, struct rte_hash_bucket *bkt, unsigne= d i) { unsigned lcore_id, n_slots; struct lcore_cache *cached_free_slots; if (h->use_local_cache) { lcore_id =3D rte_lcore_id(); cached_free_slots =3D &h->local_free_slots[lcore_id]; /* Cache full, need to free it. */ if (cached_free_slots->len =3D=3D LCORE_CACHE_SIZE) { /* Need to enqueue the free slots in global ring. */ n_slots =3D rte_ring_mp_enqueue_burst(h->free_slots, cached_free_slots->objs, LCORE_CACHE_SIZE, NULL); cached_free_slots->len -=3D n_slots; } /* Put index of new free slot in cache. */ cached_free_slots->objs[cached_free_slots->len] =3D (void *)((uintptr_t)bkt->key_idx[i]); cached_free_slots->len++; } else { rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)bkt->key_idx[i])); } } =E4=BF=AE=E5=A4=8D=E6=96=B9=E6=B3=95 1=E3=80=81=E4=BF=AE=E6=94=B9"Out of bounds" =E7=9A=84=E5=88=A4=E6=96=AD=E9= =80=BB=E8=BE=91 2=E3=80=81position=E5=9C=A8enqueue=E5=9B=9Efree_slots=E9=98=9F=E5=88=97=E4= =B9=8B=E5=89=8D=E5=8A=A01 --=20 You are receiving this mail because: You are the assignee for the bug.=